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.
Files changed (109) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +45 -0
  3. data/lib/communication/bluetooth_communication.rb +85 -0
  4. data/lib/communication/serial_port_profile.rb +71 -0
  5. data/lib/nxt.rb +111 -20
  6. data/lib/ruby-nxt.sublime-project +8 -0
  7. data/lib/ruby-nxt.sublime-workspace +288 -0
  8. data/lib/telegrams/commands/direct/get_battery_level.rb +8 -0
  9. data/lib/telegrams/commands/direct/get_current_program_name.rb +8 -0
  10. data/lib/{nxt/commands/sound.rb → telegrams/commands/direct/get_input_values.rb} +0 -0
  11. data/lib/{nxt/commands/tone.rb → telegrams/commands/direct/keep_alive.rb} +0 -0
  12. data/lib/telegrams/commands/direct/ls_get_status.rb +0 -0
  13. data/lib/telegrams/commands/direct/ls_read.rb +0 -0
  14. data/lib/telegrams/commands/direct/ls_write.rb +0 -0
  15. data/lib/telegrams/commands/direct/message_read.rb +0 -0
  16. data/lib/telegrams/commands/direct/message_write.rb +0 -0
  17. data/lib/telegrams/commands/direct/output_state.rb +229 -0
  18. data/lib/telegrams/commands/direct/play_sound_file.rb +38 -0
  19. data/lib/telegrams/commands/direct/play_tone.rb +34 -0
  20. data/lib/telegrams/commands/direct/replies/get_battery_level_reply.rb +28 -0
  21. data/lib/telegrams/commands/direct/replies/get_current_program_name_reply.rb +30 -0
  22. data/lib/telegrams/commands/direct/replies/play_sound_file_reply.rb +13 -0
  23. data/lib/telegrams/commands/direct/replies/play_tone_reply.rb +14 -0
  24. data/lib/telegrams/commands/direct/replies/reset_motor_position_reply.rb +13 -0
  25. data/lib/telegrams/commands/direct/replies/set_input_mode_reply.rb +11 -0
  26. data/lib/telegrams/commands/direct/replies/set_output_state_reply.rb +11 -0
  27. data/lib/telegrams/commands/direct/replies/start_program_reply.rb +13 -0
  28. data/lib/telegrams/commands/direct/replies/stop_program_reply.rb +13 -0
  29. data/lib/telegrams/commands/direct/replies/stop_sound_playback_reply.rb +13 -0
  30. data/lib/telegrams/commands/direct/reset_input_scaled_value.rb +0 -0
  31. data/lib/telegrams/commands/direct/reset_motor_position.rb +8 -0
  32. data/lib/telegrams/commands/direct/set_input_mode.rb +101 -0
  33. data/lib/telegrams/commands/direct/set_output_state.rb +29 -0
  34. data/lib/telegrams/commands/direct/start_program.rb +30 -0
  35. data/lib/telegrams/commands/direct/stop_program.rb +9 -0
  36. data/lib/telegrams/commands/direct/stop_sound_playback.rb +8 -0
  37. data/lib/telegrams/commands/direct_command.rb +8 -0
  38. data/lib/telegrams/commands/direct_command_reply.rb +10 -0
  39. data/lib/telegrams/commands/message_translator.rb +46 -0
  40. data/lib/telegrams/commands/system/get_device_info.rb +8 -0
  41. data/lib/telegrams/commands/system/replies/get_device_info_reply.rb +41 -0
  42. data/lib/telegrams/commands/system_command.rb +8 -0
  43. data/lib/telegrams/messages/error.rb +0 -0
  44. data/lib/telegrams/messages/message.rb +0 -0
  45. data/lib/telegrams/messages/success.rb +0 -0
  46. data/lib/telegrams/no_message_reply.rb +10 -0
  47. data/lib/telegrams/reply.rb +82 -0
  48. data/lib/telegrams/respondable_telegram.rb +29 -0
  49. data/lib/telegrams/telegram.rb +14 -0
  50. data/spec/communication/bluetooth_communication_spec.rb +170 -0
  51. data/spec/communication/serial_port_profile_spec.rb +139 -0
  52. data/spec/helper.rb +1 -0
  53. data/spec/nxt_spec.rb +438 -0
  54. data/spec/telegrams/commands/direct/get_battery_level_spec.rb +26 -0
  55. data/spec/telegrams/commands/direct/get_current_program_name_spec.rb +26 -0
  56. data/spec/telegrams/commands/direct/output_state_spec.rb +198 -0
  57. data/spec/telegrams/commands/direct/play_sound_file_spec.rb +75 -0
  58. data/spec/telegrams/commands/direct/play_tone_spec.rb +63 -0
  59. data/spec/telegrams/commands/direct/replies/get_battery_level_reply_spec.rb +40 -0
  60. data/spec/telegrams/commands/direct/replies/get_current_program_name_reply_spec.rb +33 -0
  61. data/spec/telegrams/commands/direct/replies/play_sound_file_reply_spec.rb +13 -0
  62. data/spec/telegrams/commands/direct/replies/play_tone_reply_spec.rb +14 -0
  63. data/spec/telegrams/commands/direct/replies/reset_motor_position_reply_spec.rb +13 -0
  64. data/spec/telegrams/commands/direct/replies/set_input_mode_reply_spec.rb +12 -0
  65. data/spec/telegrams/commands/direct/replies/set_output_state_reply_spec.rb +12 -0
  66. data/spec/telegrams/commands/direct/replies/start_program_reply_spec.rb +12 -0
  67. data/spec/telegrams/commands/direct/replies/stop_program_reply_spec.rb +13 -0
  68. data/spec/telegrams/commands/direct/replies/stop_sound_playback_reply_spec.rb +13 -0
  69. data/spec/telegrams/commands/direct/reset_motor_position_spec.rb +31 -0
  70. data/spec/telegrams/commands/direct/set_input_mode_spec.rb +122 -0
  71. data/spec/telegrams/commands/direct/set_output_state_spec.rb +72 -0
  72. data/spec/telegrams/commands/direct/start_program_spec.rb +58 -0
  73. data/spec/telegrams/commands/direct/stop_program_spec.rb +34 -0
  74. data/spec/telegrams/commands/direct/stop_sound_playback_spec.rb +34 -0
  75. data/spec/telegrams/commands/direct_command_reply_spec.rb +7 -0
  76. data/spec/telegrams/commands/direct_command_spec.rb +34 -0
  77. data/spec/telegrams/commands/system/get_device_info_spec.rb +16 -0
  78. data/spec/telegrams/commands/system/replies/get_device_info_reply_spec.rb +63 -0
  79. data/spec/telegrams/commands/system_command_spec.rb +26 -0
  80. data/spec/telegrams/no_message_reply_spec.rb +12 -0
  81. data/spec/telegrams/reply_spec.rb +63 -0
  82. data/spec/telegrams/respondable_telegram_spec.rb +66 -0
  83. data/spec/telegrams/telegram_spec.rb +38 -0
  84. metadata +97 -116
  85. data/README.markdown +0 -52
  86. data/Rakefile +0 -35
  87. data/lib/nxt/commands/base.rb +0 -51
  88. data/lib/nxt/commands/input.rb +0 -60
  89. data/lib/nxt/commands/output.rb +0 -105
  90. data/lib/nxt/commands/program.rb +0 -70
  91. data/lib/nxt/connectors/base.rb +0 -35
  92. data/lib/nxt/connectors/input/color.rb +0 -30
  93. data/lib/nxt/connectors/input/touch.rb +0 -11
  94. data/lib/nxt/connectors/input/ultrasonic.rb +0 -11
  95. data/lib/nxt/connectors/output/motor.rb +0 -114
  96. data/lib/nxt/errors.rb +0 -25
  97. data/lib/nxt/exceptions.rb +0 -26
  98. data/lib/nxt/interfaces/base.rb +0 -36
  99. data/lib/nxt/interfaces/serial_port.rb +0 -88
  100. data/lib/nxt/interfaces/usb.rb +0 -8
  101. data/lib/nxt/nxt_brick.rb +0 -167
  102. data/lib/nxt/patches/module.rb +0 -22
  103. data/lib/nxt/patches/string.rb +0 -29
  104. data/lib/nxt/utils/accessors.rb +0 -24
  105. data/spec/matchers.rb +0 -7
  106. data/spec/nxt/connectors/output/motor_spec.rb +0 -55
  107. data/spec/nxt/interfaces/serial_port_spec.rb +0 -73
  108. data/spec/nxt/nxt_brick_spec.rb +0 -199
  109. data/spec/spec_helper.rb +0 -4
@@ -0,0 +1,8 @@
1
+ require_relative '../direct_command'
2
+
3
+ class GetBatteryLevel < DirectCommand
4
+ def initialize
5
+ super(true)
6
+ @command = 0x0B
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require_relative '../direct_command'
2
+
3
+ class GetCurrentProgramName < DirectCommand
4
+ def initialize # cannot override require_response? since it's asking for one
5
+ super
6
+ @command = 0x11
7
+ end
8
+ end
@@ -0,0 +1,229 @@
1
+ require_relative '../message_translator'
2
+
3
+ # OutputModeFlags can be used together with the mode_flags on SetOutputState
4
+ class OutputModeFlags
5
+ class << self
6
+ # turn on the specified motor
7
+ def MOTORON
8
+ 0x01
9
+ end
10
+
11
+ # use run/brake instead of run/float in PWM
12
+ def BRAKE
13
+ 0x02
14
+ end
15
+
16
+ # turns on the regulation
17
+ def REGULATED
18
+ 0x04
19
+ end
20
+ end
21
+ end
22
+
23
+ # Regulation mode is an enumeration used to set how things work when
24
+ # in a REGULATED output mode
25
+ class RegulationMode
26
+ class << self
27
+ # no regulation will be enabled
28
+ def IDLE
29
+ 0x00
30
+ end
31
+
32
+ # power control will be enabled on the specified output
33
+ def MOTOR_SPEED
34
+ 0x01
35
+ end
36
+
37
+ # synchronization will be enabled
38
+ # (needs to be enabled on two outputs)
39
+ def MOTOR_SYNC
40
+ 0x02
41
+ end
42
+ end
43
+ end
44
+
45
+ # Run state defines how the motor behaves from where it is
46
+ # and how it gets to the new state you have given it
47
+ class RunState
48
+ class << self
49
+ # output will be idle
50
+ def IDLE
51
+ 0x00
52
+ end
53
+
54
+ # output will ramp-up
55
+ def RAMPUP
56
+ 0x10
57
+ end
58
+
59
+ # output will be running
60
+ def RUNNING
61
+ 0x20
62
+ end
63
+
64
+ # output will ramp-down
65
+ def RAMPDOWN
66
+ 0x40
67
+ end
68
+ end
69
+ end
70
+
71
+ # Output state
72
+ class OutputState
73
+ include MessageTranslator
74
+
75
+ attr_reader :port, :power, :mode_flags, :regulation_mode,
76
+ :turn_ratio, :run_state, :tacho_limit
77
+
78
+ PORTS = {
79
+ :a => 0x00,
80
+ :b => 0x01,
81
+ :c => 0x02,
82
+ :all => 0xff
83
+ }
84
+
85
+ REGULATION_MODES = {
86
+ :idle => RegulationMode.IDLE,
87
+ :motor_speed => RegulationMode.MOTOR_SPEED,
88
+ :motor_sync => RegulationMode.MOTOR_SYNC
89
+ }
90
+
91
+ RUN_STATES = {
92
+ :idle => RunState.IDLE,
93
+ :ramp_up => RunState.RAMPUP,
94
+ :running => RunState.RUNNING,
95
+ :ramp_down => RunState.RAMPDOWN
96
+ }
97
+
98
+ class << self
99
+ def ports
100
+ PORTS.keys
101
+ end
102
+
103
+ def regulation_modes
104
+ REGULATION_MODES.keys
105
+ end
106
+
107
+ def run_states
108
+ RUN_STATES.keys
109
+ end
110
+
111
+ # used with the tacho_limit
112
+ def RUN_FOREVER
113
+ 0
114
+ end
115
+ end
116
+
117
+ def initialize(options={})
118
+ options = {
119
+ :port => :all,
120
+ :power => 0,
121
+ :mode_flags => 0,
122
+ :regulation_mode => :idle,
123
+ :turn_ratio => 0,
124
+ :run_state => :idle,
125
+ :tacho_limit => 0
126
+ }.merge(options)
127
+
128
+ options.keys.each do |key|
129
+ self.send("#{key}=", options[key])
130
+ end
131
+ end
132
+
133
+ def ports
134
+ self.class.ports
135
+ end
136
+
137
+ def port=(port)
138
+ raise ArgumentError, "invalid port" unless ports.include? port
139
+
140
+ @port = port
141
+ end
142
+
143
+ def for_port(the_port)
144
+ self.port = the_port
145
+ self
146
+ end
147
+
148
+ def power=(power)
149
+ raise ArgumentError, "power must be between -100 and 100" unless power.between?(-100, 100)
150
+ @power = power
151
+ end
152
+
153
+ def with_power(power)
154
+ self.power = power
155
+ self
156
+ end
157
+
158
+ def mode_flags=(mode_flags)
159
+ raise ArgumentError, "mode_flags must be a valid combination of OutputModeFlags flags (using bitwise-OR)" unless mode_flags.between?(0, 7)
160
+ @mode_flags = mode_flags
161
+ end
162
+
163
+ def with_mode_flags(mode_flags)
164
+ self.mode_flags = mode_flags
165
+ self
166
+ end
167
+
168
+ def regulation_modes
169
+ self.class.regulation_modes
170
+ end
171
+
172
+ def regulation_mode=(regulation_mode)
173
+ raise ArgumentError, "regulation_mode must be a valid regulation mode key" unless regulation_modes.include? regulation_mode
174
+ @regulation_mode = regulation_mode
175
+ end
176
+
177
+ def with_regulation_mode(regulation_mode)
178
+ self.regulation_mode = regulation_mode
179
+ self
180
+ end
181
+
182
+ def turn_ratio=(turn_ratio)
183
+ raise ArgumentError, "turn_ratio must be between -100 and 100" unless turn_ratio.between?(-100, 100)
184
+ @turn_ratio = turn_ratio
185
+ end
186
+
187
+ def with_turn_ratio(turn_ratio)
188
+ self.turn_ratio = turn_ratio
189
+ self
190
+ end
191
+
192
+ def run_states
193
+ self.class.run_states
194
+ end
195
+
196
+ def run_state=(run_state)
197
+ raise ArgumentError, "run_state must be :idle, :running, :ramp_up, or :ramp_down" unless run_states.include?(run_state)
198
+ @run_state = run_state
199
+ end
200
+
201
+ def with_run_state(run_state)
202
+ self.run_state = run_state
203
+ self
204
+ end
205
+
206
+
207
+ def tacho_limit=(tacho_limit)
208
+ @tacho_limit = tacho_limit
209
+ end
210
+
211
+ def with_tacho_limit(tacho_limit)
212
+ self.tacho_limit = tacho_limit
213
+ self
214
+ end
215
+
216
+ def as_bytes
217
+ [
218
+ PORTS[port],
219
+ power,
220
+ mode_flags,
221
+ REGULATION_MODES[regulation_mode],
222
+ turn_ratio,
223
+ RUN_STATES[run_state]
224
+ ].concat(integer_as_ulong_bytes(tacho_limit))
225
+ end
226
+
227
+
228
+ end
229
+
@@ -0,0 +1,38 @@
1
+ require_relative '../direct_command'
2
+ require_relative '../message_translator'
3
+
4
+ class PlaySoundFile < DirectCommand
5
+ include MessageTranslator
6
+
7
+ attr_reader :name
8
+
9
+ def initialize(sound_filename, loop_sound=false, require_response=true)
10
+ raise ArgumentError, "sound_filename is required" if sound_filename.nil?
11
+
12
+ super(require_response)
13
+ @command = 0x02 # playsoundfile
14
+ @name = adjust_sound_filename(sound_filename)
15
+ @loop_sound = loop_sound
16
+ end
17
+
18
+ def loop_sound?
19
+ @loop_sound == true
20
+ end
21
+
22
+ def as_bytes
23
+ bytes = super.concat(loop_sound_as_bytes).concat(filename_as_bytes)
24
+ end
25
+
26
+ private
27
+ def loop_sound_as_bytes
28
+ boolean_as_bytes(loop_sound?)
29
+ end
30
+
31
+ def filename_as_bytes
32
+ string_as_bytes(@name)
33
+ end
34
+
35
+ def adjust_sound_filename(name)
36
+ add_default_extension_if_missing(name, 'rso')
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ require_relative '../direct_command'
2
+ require_relative '../message_translator'
3
+
4
+ class PlayTone < DirectCommand
5
+ include MessageTranslator
6
+
7
+ attr_reader :frequency, :duration
8
+
9
+ def initialize(frequency_hz, duration_ms, require_response=true)
10
+ super(require_response)
11
+ @command = 0x03
12
+ validate_arguments(frequency_hz, duration_ms)
13
+ @frequency = frequency_hz
14
+ @duration = duration_ms
15
+ end
16
+
17
+ def as_bytes
18
+ super.concat(integer_as_uword_bytes(@frequency)).concat(integer_as_uword_bytes(@duration))
19
+ end
20
+
21
+ private
22
+ def validate_arguments(frequency_hz, duration_ms)
23
+ validate_frequency(frequency_hz)
24
+ validate_duration(duration_ms)
25
+ end
26
+
27
+ def validate_frequency(frequency_hz)
28
+ raise ArgumentError, "The frequency must be between 200 and 14000 Hz" unless frequency_hz.between?(200, 14000)
29
+ end
30
+
31
+ def validate_duration(duration_ms)
32
+ raise ArgumentError, "The duration in milliseconds must be a positive number or zero" unless duration_ms >= 0
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ require_relative '../../direct_command_reply'
2
+ require_relative '../../message_translator'
3
+
4
+ class GetBatteryLevelReply < DirectCommandReply
5
+ include MessageTranslator
6
+
7
+ def initialize(bytes)
8
+ super
9
+ end
10
+
11
+ def message
12
+ integer_from_bytes(message_bytes)
13
+ end
14
+
15
+ def millivolts
16
+ message
17
+ end
18
+
19
+ def volts
20
+ millivolts/1000.0
21
+ end
22
+
23
+ private
24
+ def validate_bytes(bytes)
25
+ super
26
+ raise ArgumentError, "Must be a reply for GetBatteryLevel (0x0B)" unless bytes[1] == 0x0B
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require_relative '../../direct_command_reply'
2
+ require_relative '../../message_translator'
3
+
4
+ class GetCurrentProgramNameReply < DirectCommandReply
5
+ include MessageTranslator
6
+
7
+ def initialize(bytes)
8
+ super(bytes)
9
+ @message = parse_message_bytes_into_filename
10
+ end
11
+
12
+ def message
13
+ @message
14
+ end
15
+
16
+ def program_name
17
+ message
18
+ end
19
+
20
+ private
21
+ def validate_bytes(bytes)
22
+ super(bytes)
23
+ raise ArgumentError, "reply must be for a GetCurrentProgramName command" unless bytes[1] == 0x11
24
+ end
25
+
26
+ def parse_message_bytes_into_filename
27
+ string_from_bytes(message_bytes)
28
+ end
29
+
30
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../../direct_command_reply'
2
+
3
+ class PlaySoundFileReply < 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 PlaySoundFile command" unless bytes[1] == 0x02
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../../direct_command_reply'
2
+
3
+ class PlayToneReply < DirectCommandReply
4
+ def initialize(bytes)
5
+ super(bytes)
6
+ end
7
+
8
+
9
+ def validate_bytes(bytes)
10
+ super(bytes)
11
+ raise ArgumentError, "must be a reply for the PlayTone command" unless bytes[1] == 0x03
12
+ end
13
+
14
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../../direct_command_reply'
2
+
3
+ class ResetMotorPositionReply < 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 ResetMotorPosition command" unless bytes[1] == 0x0A
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../../direct_command_reply'
2
+
3
+ class SetInputModeReply < 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 SetInputMode command" unless bytes[1] == 0x05
10
+ end
11
+ end