hybridgroup-crubyflie 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +5 -0
  5. data/LICENSE.txt +674 -0
  6. data/README.md +127 -0
  7. data/Rakefile +15 -0
  8. data/bin/crubyflie +94 -0
  9. data/configs/joystick_default.yaml +106 -0
  10. data/crubyflie.gemspec +50 -0
  11. data/examples/params_and_logging.rb +87 -0
  12. data/lib/crubyflie/crazyflie/commander.rb +54 -0
  13. data/lib/crubyflie/crazyflie/console.rb +67 -0
  14. data/lib/crubyflie/crazyflie/log.rb +383 -0
  15. data/lib/crubyflie/crazyflie/log_conf.rb +57 -0
  16. data/lib/crubyflie/crazyflie/param.rb +220 -0
  17. data/lib/crubyflie/crazyflie/toc.rb +239 -0
  18. data/lib/crubyflie/crazyflie/toc_cache.rb +87 -0
  19. data/lib/crubyflie/crazyflie.rb +282 -0
  20. data/lib/crubyflie/crazyradio/crazyradio.rb +301 -0
  21. data/lib/crubyflie/crazyradio/radio_ack.rb +48 -0
  22. data/lib/crubyflie/crubyflie_logger.rb +74 -0
  23. data/lib/crubyflie/driver/crtp_packet.rb +146 -0
  24. data/lib/crubyflie/driver/radio_driver.rb +363 -0
  25. data/lib/crubyflie/exceptions.rb +36 -0
  26. data/lib/crubyflie/input/input_reader.rb +190 -0
  27. data/lib/crubyflie/input/joystick_input_reader.rb +328 -0
  28. data/lib/crubyflie/version.rb +22 -0
  29. data/lib/crubyflie.rb +36 -0
  30. data/spec/commander_spec.rb +67 -0
  31. data/spec/console_spec.rb +76 -0
  32. data/spec/crazyflie_spec.rb +176 -0
  33. data/spec/crazyradio_spec.rb +228 -0
  34. data/spec/crtp_packet_spec.rb +79 -0
  35. data/spec/crubyflie_logger_spec.rb +39 -0
  36. data/spec/crubyflie_spec.rb +21 -0
  37. data/spec/input_reader_spec.rb +136 -0
  38. data/spec/joystick_cfg.yaml +44 -0
  39. data/spec/joystick_input_reader_spec.rb +323 -0
  40. data/spec/log_spec.rb +266 -0
  41. data/spec/param_spec.rb +166 -0
  42. data/spec/radio_ack_spec.rb +43 -0
  43. data/spec/radio_driver_spec.rb +227 -0
  44. data/spec/spec_helper.rb +53 -0
  45. data/spec/toc_cache_spec.rb +87 -0
  46. data/spec/toc_spec.rb +187 -0
  47. data/tools/sdl-joystick-axis.rb +69 -0
  48. metadata +225 -0
@@ -0,0 +1,44 @@
1
+ :type: "Joystick"
2
+ :axis:
3
+ 0:
4
+ :description: "Roll Axis"
5
+ :action: :roll
6
+ :input_range: "-32768:32767"
7
+ :output_range: "-30:30"
8
+ :max_change_rate: 600
9
+ :dead_zone: "-100:100"
10
+ :invert: false
11
+ :calibration: 0
12
+ 1:
13
+ :description: "Pitch Axis"
14
+ :action: :pitch
15
+ :input_range: "-32768:32767"
16
+ :output_range: "-30:30"
17
+ :max_change_rate: 600
18
+ :dead_zone: "0:0"
19
+ :invert: true
20
+ :calibration: 0
21
+ 2:
22
+ :description: "Yaw Axis"
23
+ :action: :yaw
24
+ :input_range: "-32768:32767"
25
+ :output_range: "-30:30"
26
+ :max_change_rate: 800
27
+ :dead_zone: "-1000:1000"
28
+ :invert: false
29
+ :calibration: 0
30
+ 3:
31
+ :description: "Thrust axis"
32
+ :action: :thrust
33
+ :input_range: "-32768:32767"
34
+ :output_range: "0:80"
35
+ :max_change_rate: 40000
36
+ :dead_zone: "-100:100"
37
+ :invert: true
38
+ :calibration: 0
39
+
40
+ :buttons:
41
+ 0:
42
+ :action: :switch_xmode
43
+ 1:
44
+ :action: :close_link
@@ -0,0 +1,323 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'input/joystick_input_reader'
20
+
21
+ describe Joystick do
22
+
23
+ before :each do
24
+ @sdl_joystick = double("Joystick")
25
+ allow(SDL::Joystick).to receive(:update_all)
26
+ allow(SDL).to receive(:init).with(SDL::INIT_JOYSTICK)
27
+ allow(SDL::Joystick).to receive(:num).and_return(3)
28
+ allow(SDL::Joystick).to receive(:open).and_return(@sdl_joystick)
29
+ allow(SDL::Joystick).to receive(:index_name).and_return("My Joystick")
30
+ allow(SDL::Joystick).to receive(:poll).with(false)
31
+ expect(SDL::Joystick).not_to receive(:poll).with(true)
32
+ @path = File.join(File.dirname(__FILE__), 'joystick_cfg.yaml')
33
+
34
+ @joystick = Joystick.new(@path)
35
+
36
+ @logger = @joystick.logger
37
+ allow(@logger).to receive(:info)
38
+ @joystick.init()
39
+ end
40
+
41
+ describe "#initialize" do
42
+ it "should initialize a valid joystick supposing things go well" do
43
+ @joystick.axis.should == {
44
+ 0 => :roll,
45
+ 1 => :pitch,
46
+ 2 => :yaw,
47
+ 3 => :thrust
48
+ }
49
+
50
+ @joystick.buttons.should == {
51
+ 0 => :switch_xmode,
52
+ 1 => :close_link
53
+ }
54
+ end
55
+ end
56
+
57
+ describe "#read_configuration" do
58
+ it "should read a configuration correctly" do
59
+ cfg = {
60
+ :type => "Joystick",
61
+ :axis => {0 => {:action => :yaw}},
62
+ :buttons => {0 => {:action => :roll}}
63
+ }
64
+ expect(YAML).to receive(:load_file).and_return(cfg)
65
+
66
+ axis, buttons = @joystick.read_configuration('path')
67
+ @joystick.config[:type].should == "Joystick"
68
+ axis.should == { 0 => :yaw }
69
+ buttons.should == { 0 => :roll }
70
+ end
71
+
72
+ it "should raise exception if it cannot load the configuration" do
73
+ expect {
74
+ @joystick.read_configuration('baa')
75
+ }.to raise_exception(JoystickException)
76
+ end
77
+
78
+ it "should raise exception if the configuration type is bad" do
79
+ cfg = {
80
+ :type => "BBOBOBO",
81
+ :axis => {0 => {:action => :yaw}},
82
+ :buttons => {0 => {:action => :roll}}
83
+ }
84
+ expect(YAML).to receive(:load_file).and_return(cfg)
85
+ m = "Configuration is not of type Joystick"
86
+ expect {
87
+ @joystick.read_configuration('baa')
88
+ }.to raise_exception(JoystickException, m)
89
+ end
90
+
91
+ it "should raise exception if the axis or buttons are missing" do
92
+ cfg = {
93
+ :type => "Joystick",
94
+ :buttons => {0 => {:action => :yaw}},
95
+ }
96
+ expect(YAML).to receive(:load_file).and_return(cfg)
97
+ expect {
98
+ @joystick.read_configuration('baa')
99
+ }.to raise_exception(JoystickException, "No axis section")
100
+ end
101
+
102
+ it "should raise exception if an axis has no action" do
103
+ cfg = {
104
+ :type => "Joystick",
105
+ :axis => {0 => {:invert => true}},
106
+ :buttons => {0 => {:action => :roll}}
107
+ }
108
+ expect(YAML).to receive(:load_file).and_return(cfg)
109
+ expect {
110
+ @joystick.read_configuration('baa')
111
+ }.to raise_exception(JoystickException, "Axis 0 needs an action")
112
+ end
113
+ end
114
+
115
+ describe "#init_sdl" do
116
+ it "should raise an exception if the joystick index is invalid" do
117
+ expect {
118
+ js = Joystick.new(@path, 33)
119
+ allow(js.logger).to receive(:info)
120
+ js.init()
121
+ }.to raise_exception(JoystickException, "No valid joystick index")
122
+ end
123
+
124
+ it "should open the joystick" do
125
+ expect(SDL::Joystick).to receive(:open).with(2)
126
+ js = Joystick.new(@path, 2)
127
+ allow(js.logger).to receive(:info)
128
+ js.init()
129
+ end
130
+ end
131
+
132
+ describe "#read_axis" do
133
+ it "should read the axis value with all the defaults" do
134
+ config = {
135
+ :type => "Joystick",
136
+ :axis => {
137
+ 8 =>{
138
+ :action => :test,
139
+ }
140
+ }
141
+ }
142
+ expect(YAML).to receive(:load_file).and_return(config)
143
+ expect(@sdl_joystick).to receive(:axis).with(8).and_return(-32768)
144
+ @joystick.read_configuration('baa')
145
+ value = @joystick.read_axis(8)
146
+ value.should == -30
147
+ end
148
+
149
+ it "should put values out of range in range" do
150
+ config = {
151
+ :type => "Joystick",
152
+ :axis => {
153
+ 8 =>{
154
+ :action => :test,
155
+ }
156
+ }
157
+ }
158
+ expect(YAML).to receive(:load_file).and_return(config)
159
+ expect(@sdl_joystick).to receive(:axis).with(8).and_return(-40000)
160
+ @joystick.read_configuration('baa')
161
+ value = @joystick.read_axis(8)
162
+ value.should == -30
163
+ end
164
+
165
+ it "should invert values if requested" do
166
+ config = {
167
+ :type => "Joystick",
168
+ :axis => {
169
+ 8 =>{
170
+ :action => :test,
171
+ :invert => true
172
+ }
173
+ }
174
+ }
175
+ expect(YAML).to receive(:load_file).and_return(config)
176
+ expect(@sdl_joystick).to receive(:axis).with(8).and_return(-32767)
177
+ @joystick.read_configuration('baa')
178
+ value = @joystick.read_axis(8)
179
+ value.should == 30
180
+ end
181
+
182
+ it "should put values in the deadzone as 0" do
183
+ config = {
184
+ :type => "Joystick",
185
+ :axis => {
186
+ 8 =>{
187
+ :action => :test,
188
+ :dead_zone => "-40:40"
189
+ }
190
+ }
191
+ }
192
+ expect(YAML).to receive(:load_file).and_return(config)
193
+ expect(@sdl_joystick).to receive(:axis).with(8).and_return(23)
194
+ @joystick.read_configuration('baa')
195
+ value = @joystick.read_axis(8)
196
+ value.should == 0
197
+ end
198
+
199
+ it "should normalize the thrust correctly" do
200
+ config = {
201
+ :type => "Joystick",
202
+ :axis => {
203
+ 8 =>{
204
+ :action => :thrust,
205
+ :output_range => "0:100"
206
+ }
207
+ }
208
+ }
209
+ expect(YAML).to receive(:load_file).and_return(config)
210
+ expect(@sdl_joystick).to receive(:axis).with(8).and_return(32767)
211
+ @joystick.read_configuration('baa')
212
+ value = @joystick.read_axis(8)
213
+ value.should == 60000
214
+ end
215
+
216
+ it "should throotle the change rate correctly" do
217
+ config = {
218
+ :type => "Joystick",
219
+ :axis => {
220
+ 8 => {
221
+ :action => :thrust,
222
+ :output_range => "0:100",
223
+ :input_range => "100:200",
224
+ :max_change_rate => 1,
225
+ :last_poll => 0.500,
226
+ :last_value => 34750
227
+ }
228
+ }
229
+ }
230
+ expect(YAML).to receive(:load_file).and_return(config)
231
+
232
+ allow(Time).to receive(:now).and_return(1.0) # 0.5 secs after
233
+ expect(@sdl_joystick).to receive(:axis).with(8).and_return(140)
234
+ @joystick.read_configuration('baa')
235
+ value = @joystick.read_axis(8)
236
+ value.should == 34497.5
237
+ end
238
+
239
+ it "should not throotle the change rate when increasing thrust" do
240
+ config = {
241
+ :type => "Joystick",
242
+ :axis => {
243
+ 8 =>{
244
+ :action => :thrust,
245
+ :output_range => "0:100",
246
+ :input_range => "0:100",
247
+ :max_change_rate => 1,
248
+ :last_poll => 0.500,
249
+ :last_value => 50
250
+ }
251
+ }
252
+ }
253
+ expect(YAML).to receive(:load_file).and_return(config)
254
+
255
+ allow(Time).to receive(:now).and_return(1.0) # 0.5 secs after
256
+ expect(@sdl_joystick).to receive(:axis).with(8).and_return(100)
257
+ @joystick.read_configuration('baa')
258
+ value = @joystick.read_axis(8)
259
+ value.should == 60000
260
+ end
261
+ end
262
+
263
+ describe "#normalize_thrust" do
264
+ it "should return values within the range expected by the CF" do
265
+ v = @joystick.send(:normalize_thrust, 5000,
266
+ {
267
+ :start => -10000.0,
268
+ :end => 10000.0,
269
+ :width => 20000.0
270
+ },{
271
+ :start => 0.0,
272
+ :end => 80.0,
273
+ :width => 80.0
274
+ })
275
+ v.should == 34750
276
+ v.should be_an_instance_of Fixnum
277
+ end
278
+
279
+ it "should set values under the given range to the min" do
280
+ v = @joystick.send(:normalize_thrust, 0,
281
+ {
282
+ :start => -10000.0,
283
+ :end => 10000.0,
284
+ :width => 20000.to_f
285
+ },{
286
+ :start => 30.0,
287
+ :end => 80.0,
288
+ :width => 50.0
289
+ })
290
+ v.should == 24650 # 30% of 9500-60000
291
+ v.should be_an_instance_of Fixnum
292
+ end
293
+
294
+ it "should set values over the given range to the max" do
295
+ v = @joystick.send(:normalize_thrust, 32767,
296
+ {
297
+ :start => -10000.0,
298
+ :end => +10000.0,
299
+ :width => 20000.to_f
300
+ },{
301
+ :start => 0.0,
302
+ :end => 80.0,
303
+ :width => 80.0
304
+ })
305
+ v.should == 49900 # 80% of 9500-60000
306
+ v.should be_an_instance_of Fixnum
307
+ end
308
+ end
309
+
310
+ describe "#read button" do
311
+ it "should return 1 when pressed" do
312
+ expect(@sdl_joystick).to receive(:button).and_return(true)
313
+ v = @joystick.send(:read_button, 1)
314
+ v.should == 1
315
+ end
316
+
317
+ it "should return -1 when not pressed" do
318
+ expect(@sdl_joystick).to receive(:button).and_return(false)
319
+ v = @joystick.send(:read_button, 0)
320
+ v.should == 0
321
+ end
322
+ end
323
+ end
data/spec/log_spec.rb ADDED
@@ -0,0 +1,266 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'crazyflie/log'
20
+
21
+
22
+ describe LogTOCElement do
23
+ describe "#initialize" do
24
+ it "should initialize correctly" do
25
+ data = [5, 23].pack('C*') + ['hello', 'world'].pack('Z*Z*')
26
+ lte = LogTOCElement.new(data)
27
+ lte.ident.should == 5
28
+ lte.group.should == 'hello'
29
+ lte.name.should == 'world'
30
+ lte.ctype.should == 'float'
31
+ lte.directive.should == 'e'
32
+ lte.access.should == 0x10
33
+ end
34
+ end
35
+ end
36
+
37
+ describe LogBlock do
38
+ describe "#initialize" do
39
+ it "should count blocks correctly" do
40
+ b1 = LogBlock.new([]) # 0
41
+ b2 = LogBlock.new([]) # 1
42
+ b3 = LogBlock.new([]) # 2
43
+ b3.ident.should == 2
44
+ end
45
+ end
46
+
47
+ describe "#unpack_log_data" do
48
+ it "should unpack some binary data and call the callback" do
49
+ result = nil
50
+ cb = Proc.new do |r|
51
+ result = r
52
+ end
53
+
54
+ var1 = LogConfVariable.new("var1", true, 0, 1)
55
+ var2 = LogConfVariable.new("var2", true, 0, 2)
56
+ var3 = LogConfVariable.new("var3", true, 0, 3)
57
+
58
+ variables = [var1, var2, var3]
59
+
60
+ # 1 uint8, 1 uint16 and 1 uint32
61
+ data = [255].pack('C') + [65535].pack('S<') + [16777215].pack('L<')
62
+
63
+ b = LogBlock.new(variables) #3
64
+ b.data_callback = cb
65
+ b.unpack_log_data(data)
66
+ result.should == {
67
+ 'var1' => 255,
68
+ 'var2' => 65535,
69
+ 'var3' => 16777215
70
+ }
71
+ end
72
+ end
73
+ end
74
+
75
+ describe Log do
76
+ before :each do
77
+ @crazyflie = double("Crazyflie")
78
+ @queue = Queue.new
79
+ allow(@crazyflie).to receive(:crtp_queues).and_return({:logging =>
80
+ @queue})
81
+ allow(@crazyflie).to receive(:cache_folder).and_return(nil)
82
+
83
+ @log = Log.new(@crazyflie)
84
+ @logger = @log.logger
85
+ end
86
+
87
+ describe "#initialize" do
88
+ it "should intialize the Log facility" do
89
+ @log.toc.toc.should == {}
90
+ @log.log_blocks.should == {}
91
+ end
92
+ end
93
+
94
+ describe "#refresh_toc" do
95
+ it "send the packet and fetch the TOC from the crazyflie" do
96
+ port = Crazyflie::CRTP_PORTS[:logging]
97
+ channel = TOC_CHANNEL
98
+ expect(@crazyflie).to receive(:send_packet).once
99
+ expect(@log.toc).to receive(:fetch_from_crazyflie).with(
100
+ @crazyflie,
101
+ port,
102
+ @queue)
103
+ @log.refresh_toc()
104
+ end
105
+ end
106
+
107
+ describe "#create_log_block" do
108
+ it "should send the create block package for toc variables" do
109
+ log_conf = double("LogConf")
110
+
111
+ var1 = LogConfVariable.new("var1", true, 0, 1)
112
+
113
+ var2 = LogConfVariable.new("var2", false, 0, 2, 2)
114
+ expect(var2).not_to receive(:name)
115
+
116
+ var3 = LogConfVariable.new("var3", true, 0, 3)
117
+ expect(var3).not_to receive(:address)
118
+
119
+ variables = [var1, var2, var3]
120
+ log_conf = LogConf.new(variables, {:period => 200})
121
+
122
+ # It is the 4th call to logblock.new in these specs
123
+ expect(@logger).to receive(:debug).with("Adding block 4")
124
+
125
+ packet = CRTPPacket.new()
126
+ packet.modify_header(nil, CRTP_PORTS[:logging],
127
+ LOG_SETTINGS_CHANNEL)
128
+
129
+ packet.data = [Log::CMD_CREATE_BLOCK] + [4] +
130
+ [1] + [1] + [2] + [2,0,0,0] + [3] + [32]
131
+
132
+ toc1 = TOCElement.new({:ident => 1})
133
+ toc3 = TOCElement.new({:ident => 32})
134
+ expect(@log.toc).to receive(:[]).with('var1').and_return(toc1)
135
+ expect(@log.toc).to receive(:[]).with('var3').and_return(toc3)
136
+
137
+ expect(@crazyflie).to receive(:send_packet) do |pk|
138
+ packet.header.should == pk.header
139
+ packet.data.should == pk.data
140
+ end
141
+ @log.create_log_block(log_conf).should == 4
142
+ end
143
+ end
144
+
145
+ describe "#start_logging" do
146
+ it "should send the start logging packet" do
147
+ logblock = double("logblock")
148
+ expect(logblock).to receive(:period).and_return(30)
149
+ expect(logblock).to receive(:data_callback=).with(an_instance_of(Proc))
150
+ expect(@log.log_blocks).to receive(:[]).with(5).and_return(logblock)
151
+ expect(@logger).to receive(:debug)
152
+ expect(@crazyflie).to receive(:send_packet) do |pk|
153
+ pk.data.should == [CMD_START_LOGGING, 5, 30]
154
+ end
155
+ @log.start_logging(5) do |values|
156
+ end
157
+ end
158
+ end
159
+
160
+ describe "#stop_logging" do
161
+ it "should send the stop logging packet" do
162
+ block = double("block")
163
+ expect(@log.log_blocks).to receive(:[]).with(5).and_return(block)
164
+ expect(@logger).to receive(:debug)
165
+ expect(@crazyflie).to receive(:send_packet) do |pk|
166
+ pk.data.should == [CMD_STOP_LOGGING, 5]
167
+ end
168
+ @log.stop_logging(5)
169
+ end
170
+ end
171
+
172
+ describe "#delete_block" do
173
+ it "should delete the block" do
174
+ block = double("block")
175
+ expect(@crazyflie).to receive(:send_packet) do |pk|
176
+ pk.data.should == [CMD_DELETE_BLOCK, 5]
177
+ end
178
+ expect(@log.log_blocks).to receive(:delete).with(5).and_return({})
179
+
180
+ @log.delete_block(5)
181
+ end
182
+ end
183
+
184
+ describe "#[]" do
185
+ it "should return a block with the given ID" do
186
+ expect(@log.log_blocks).to receive(:[]).with(3)
187
+ @log[3]
188
+ end
189
+ end
190
+
191
+ describe "#start_packet_reader_thread" do
192
+ it "should start a thread and process a packet" do
193
+ packet = CRTPPacket.new()
194
+ packet.modify_header(nil, nil, 3)
195
+ packet.channel.should == 3 # We dont process this one
196
+ do_this = receive(:pop).and_return(packet).at_least(:once)
197
+ expect(@queue).to do_this
198
+ expect(@logger).to receive(:debug).at_least(:once)
199
+ @log.start_packet_reader_thread
200
+ sleep 0.1
201
+ @log.stop_packet_reader_thread
202
+ end
203
+ end
204
+
205
+ describe "#handle_settings_packet" do
206
+ # This has not many secret
207
+ it "should go to CMD_CREATE_BLOCK case without error" do
208
+ packet = CRTPPacket.new()
209
+ packet.data = [CMD_CREATE_BLOCK, 33, 0]
210
+ expect(@log).not_to receive(:puts)
211
+ expect(@logger).to receive(:error).with("No log entry for 33")
212
+ @log.send(:handle_settings_packet, packet)
213
+ end
214
+
215
+ it "should go to CMD_CREATE_BLOCK case with error" do
216
+ packet = CRTPPacket.new()
217
+ packet.data = [CMD_CREATE_BLOCK, 33, 3]
218
+ expect(@logger).to receive(:error).with("Error creating block 33: 3")
219
+ expect(@log.log_blocks).to receive(:[]).with(33).and_return({})
220
+ @log.send(:handle_settings_packet, packet)
221
+ end
222
+
223
+ it "should go to CMD_START_LOGGING case without error" do
224
+ packet = CRTPPacket.new()
225
+ packet.data = [CMD_START_LOGGING, 33, 0]
226
+ expect(@logger).to receive(:debug).with("Logging started for 33")
227
+ @log.send(:handle_settings_packet, packet)
228
+ end
229
+
230
+ it "should go to CMD_START_LOGGING case with error" do
231
+ packet = CRTPPacket.new()
232
+ packet.data = [CMD_START_LOGGING, 33, 3]
233
+ expect(@logger).to receive(:error).with("Error starting to log 33: 3")
234
+ @log.send(:handle_settings_packet, packet)
235
+ end
236
+ end
237
+
238
+ describe "#handle_logdata_packet" do
239
+ it "should warn if no block exist" do
240
+ expect(@log.log_blocks).to receive(:[]).with(33).and_return(nil)
241
+ m = "No entry for logdata for block 33"
242
+ expect(@logger).to receive(:error).with(m)
243
+ packet = CRTPPacket.new()
244
+ packet.data = [33, 44, 45, 46]
245
+ @log.send(:handle_logdata_packet, packet)
246
+ end
247
+
248
+ it "should call the unpack log data if the block exists" do
249
+ block = double("Block")
250
+ expect(block).to receive(:unpack_log_data).with([46,47].pack('C*'))
251
+ expect(@log.log_blocks).to receive(:[]).with(33).and_return(block)
252
+ expect(@logger).not_to receive(:error)
253
+ packet = CRTPPacket.new()
254
+ packet.data = [33, 44, 45, 46, 46, 47]
255
+ @log.send(:handle_logdata_packet, packet)
256
+ end
257
+ end
258
+
259
+ describe "#packet_factory" do
260
+ it "should return a new packet on logging port and settings channel" do
261
+ pk = @log.send(:packet_factory)
262
+ pk.channel.should == LOG_SETTINGS_CHANNEL
263
+ pk.port.should == CRTP_PORTS[:logging]
264
+ end
265
+ end
266
+ end