Revert "Device/Driver/LX: Add small delay after baud rate change"
[xcsoar.git] / test / src / TestDriver.cpp
blob572ec56d79e2fe5d8a9bdb360fc9653fd1f5320f
1 /* Copyright_License {
3 XCSoar Glide Computer - http://www.xcsoar.org/
4 Copyright (C) 2000-2013 The XCSoar Project
5 A detailed list of copyright holders can be found in the file "AUTHORS".
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "Device/Driver/Generic.hpp"
24 #include "Device/Driver/AltairPro.hpp"
25 #include "Device/Driver/BlueFlyVario.hpp"
26 #include "Device/Driver/BorgeltB50.hpp"
27 #include "Device/Driver/CAI302.hpp"
28 #include "Device/Driver/Condor.hpp"
29 #include "Device/Driver/CProbe.hpp"
30 #include "Device/Driver/EW.hpp"
31 #include "Device/Driver/EWMicroRecorder.hpp"
32 #include "Device/Driver/Eye.hpp"
33 #include "Device/Driver/FLARM.hpp"
34 #include "Device/Driver/FlymasterF1.hpp"
35 #include "Device/Driver/FlyNet.hpp"
36 #include "Device/Driver/Flytec.hpp"
37 #include "Device/Driver/GTAltimeter.hpp"
38 #include "Device/Driver/LevilAHRS_G.hpp"
39 #include "Device/Driver/Leonardo.hpp"
40 #include "Device/Driver/LX.hpp"
41 #include "Device/Driver/LX/Internal.hpp"
42 #include "Device/Driver/ILEC.hpp"
43 #include "Device/Driver/IMI.hpp"
44 #include "Device/Driver/PosiGraph.hpp"
45 #include "Device/Driver/Vega.hpp"
46 #include "Device/Driver/Volkslogger.hpp"
47 #include "Device/Driver/Westerboer.hpp"
48 #include "Device/Driver/Zander.hpp"
49 #include "Device/Driver.hpp"
50 #include "Device/Parser.hpp"
51 #include "Device/device.hpp"
52 #include "Device/Port/NullPort.hpp"
53 #include "Device/Declaration.hpp"
54 #include "Logger/Settings.hpp"
55 #include "Plane/Plane.hpp"
56 #include "NMEA/Info.hpp"
57 #include "Protection.hpp"
58 #include "Input/InputEvents.hpp"
59 #include "Engine/Waypoint/Waypoint.hpp"
60 #include "Operation/Operation.hpp"
61 #include "FaultInjectionPort.hpp"
62 #include "TestUtil.hpp"
63 #include "Profile/DeviceConfig.hpp"
64 #include "Units/System.hpp"
66 static const DeviceConfig dummy_config = DeviceConfig();
69 * Unit tests
72 static void
73 TestGeneric()
75 NMEAParser parser;
77 NMEAInfo nmea_info;
78 nmea_info.Reset();
79 nmea_info.clock = fixed(1);
80 nmea_info.alive.Update(nmea_info.clock);
82 /* no GPS reception */
83 ok1(parser.ParseLine("$GPRMC,082310,V,,,,,230610*3f",
84 nmea_info));
85 ok1(nmea_info.alive);
86 ok1(!nmea_info.location_available);
87 ok1(nmea_info.date_time_utc.year == 2010);
88 ok1(nmea_info.date_time_utc.month == 6);
89 ok1(nmea_info.date_time_utc.day == 23);
90 ok1(nmea_info.date_time_utc.hour == 8);
91 ok1(nmea_info.date_time_utc.minute == 23);
92 ok1(nmea_info.date_time_utc.second == 10);
94 /* got a GPS fix */
95 ok1(parser.ParseLine("$GPRMC,082311,A,5103.5403,N,00741.5742,E,055.3,022.4,230610,000.3,W*6C",
96 nmea_info));
97 ok1(nmea_info.alive);
98 ok1(nmea_info.location_available);
99 ok1(nmea_info.date_time_utc.hour == 8);
100 ok1(nmea_info.date_time_utc.minute == 23);
101 ok1(nmea_info.date_time_utc.second == 11);
102 ok1(equals(nmea_info.location.longitude, 7.693));
103 ok1(equals(nmea_info.location.latitude, 51.059));
104 ok1(!nmea_info.baro_altitude_available);
106 /* baro altitude (proprietary Garmin sentence) */
107 ok1(parser.ParseLine("$PGRMZ,100,m,3*11", nmea_info));
108 ok1(nmea_info.baro_altitude_available);
109 ok1(equals(nmea_info.baro_altitude, 100));
112 static void
113 TestTasman()
115 NMEAParser parser;
117 NMEAInfo nmea_info;
118 nmea_info.Reset();
119 nmea_info.clock = fixed(1);
121 ok1(parser.ParseLine("$PTAS1,200,200,02426,000*25", nmea_info));
122 ok1(nmea_info.total_energy_vario_available);
123 ok1(equals(nmea_info.total_energy_vario, fixed(0)));
124 ok1(nmea_info.pressure_altitude_available);
125 ok1(equals(nmea_info.pressure_altitude, Units::ToSysUnit(fixed(426), Unit::FEET)));
126 ok1(nmea_info.airspeed_available);
127 ok1(equals(nmea_info.true_airspeed, fixed(0)));
129 ok1(parser.ParseLine("$PTAS1,234,000,00426,062*26", nmea_info));
130 ok1(nmea_info.total_energy_vario_available);
131 ok1(equals(nmea_info.total_energy_vario, Units::ToSysUnit(fixed(3.4), Unit::KNOTS)));
132 ok1(nmea_info.pressure_altitude_available);
133 ok1(equals(nmea_info.pressure_altitude, Units::ToSysUnit(fixed(-1574), Unit::FEET)));
134 ok1(nmea_info.airspeed_available);
135 ok1(equals(nmea_info.true_airspeed, Units::ToSysUnit(fixed(62), Unit::KNOTS)));
138 static void
139 TestFLARM()
141 NMEAParser parser;
143 NMEAInfo nmea_info;
144 nmea_info.Reset();
145 nmea_info.clock = fixed(1);
147 ok1(parser.ParseLine("$PFLAU,3,1,1,1,0*50",
148 nmea_info));
149 ok1(nmea_info.flarm.status.rx == 3);
150 ok1(nmea_info.flarm.status.tx);
151 ok1(nmea_info.flarm.status.gps == FlarmStatus::GPSStatus::GPS_2D);
152 ok1(nmea_info.flarm.status.alarm_level == FlarmTraffic::AlarmType::NONE);
153 ok1(nmea_info.flarm.traffic.GetActiveTrafficCount() == 0);
154 ok1(!nmea_info.flarm.traffic.new_traffic);
156 ok1(parser.ParseLine("$PFLAA,0,100,-150,10,2,DDA85C,123,13,24,1.4,2*7f",
157 nmea_info));
158 ok1(nmea_info.flarm.traffic.new_traffic);
159 ok1(nmea_info.flarm.traffic.GetActiveTrafficCount() == 1);
161 FlarmId id = FlarmId::Parse("DDA85C", NULL);
163 FlarmTraffic *traffic = nmea_info.flarm.traffic.FindTraffic(id);
164 if (ok1(traffic != NULL)) {
165 ok1(traffic->valid);
166 ok1(traffic->alarm_level == FlarmTraffic::AlarmType::NONE);
167 ok1(equals(traffic->relative_north, 100));
168 ok1(equals(traffic->relative_east, -150));
169 ok1(equals(traffic->relative_altitude, 10));
170 ok1(equals(traffic->track, 123));
171 ok1(traffic->track_received);
172 ok1(equals(traffic->turn_rate, 13));
173 ok1(traffic->turn_rate_received);
174 ok1(equals(traffic->speed, 24));
175 ok1(traffic->speed_received);
176 ok1(equals(traffic->climb_rate, 1.4));
177 ok1(traffic->climb_rate_received);
178 ok1(traffic->type == FlarmTraffic::AircraftType::TOW_PLANE);
179 ok1(!traffic->stealth);
180 } else {
181 skip(16, 0, "traffic == NULL");
184 ok1(parser.ParseLine("$PFLAA,2,20,10,24,2,DEADFF,,,,,1*46",
185 nmea_info));
186 ok1(nmea_info.flarm.traffic.GetActiveTrafficCount() == 2);
188 id = FlarmId::Parse("DEADFF", NULL);
189 traffic = nmea_info.flarm.traffic.FindTraffic(id);
190 if (ok1(traffic != NULL)) {
191 ok1(traffic->valid);
192 ok1(traffic->alarm_level == FlarmTraffic::AlarmType::IMPORTANT);
193 ok1(equals(traffic->relative_north, 20));
194 ok1(equals(traffic->relative_east, 10));
195 ok1(equals(traffic->relative_altitude, 24));
196 ok1(!traffic->track_received);
197 ok1(!traffic->turn_rate_received);
198 ok1(!traffic->speed_received);
199 ok1(!traffic->climb_rate_received);
200 ok1(traffic->type == FlarmTraffic::AircraftType::GLIDER);
201 ok1(traffic->stealth);
202 } else {
203 skip(12, 0, "traffic == NULL");
206 ok1(parser.ParseLine("$PFLAA,0,1206,574,21,2,DDAED5,196,,32,1.0,1*10",
207 nmea_info));
208 ok1(nmea_info.flarm.traffic.GetActiveTrafficCount() == 3);
210 id = FlarmId::Parse("DDAED5", NULL);
211 traffic = nmea_info.flarm.traffic.FindTraffic(id);
212 if (ok1(traffic != NULL)) {
213 ok1(traffic->valid);
214 ok1(traffic->alarm_level == FlarmTraffic::AlarmType::NONE);
215 ok1(equals(traffic->relative_north, 1206));
216 ok1(equals(traffic->relative_east, 574));
217 ok1(equals(traffic->relative_altitude, 21));
218 ok1(equals(traffic->track, 196));
219 ok1(traffic->track_received);
220 ok1(!traffic->turn_rate_received);
221 ok1(equals(traffic->speed, 32));
222 ok1(traffic->speed_received);
223 ok1(equals(traffic->climb_rate, 1.0));
224 ok1(traffic->climb_rate_received);
225 ok1(traffic->type == FlarmTraffic::AircraftType::GLIDER);
226 ok1(!traffic->stealth);
227 } else {
228 skip(15, 0, "traffic == NULL");
232 static void
233 TestAltairRU()
235 NullPort null;
236 Device *device = altair_pro_driver.CreateOnPort(dummy_config, null);
237 ok1(device != NULL);
239 NMEAInfo nmea_info;
240 nmea_info.Reset();
241 nmea_info.clock = fixed(1);
243 ok1(device->ParseNMEA("$PTFRS,1,0,0,0,0,0,0,0,5,1,10,0,3,1338313437,0,0,0,,,2*4E",
244 nmea_info));
246 ok1(nmea_info.engine_noise_level_available);
247 ok1(nmea_info.engine_noise_level == 5);
248 ok1(!nmea_info.voltage_available);
250 nmea_info.Reset();
251 nmea_info.clock = fixed(1);
253 ok1(device->ParseNMEA("$PTFRS,1,0,0,0,0,0,0,0,342,1,10,0,3,1338313438,0,0,12743,,,2*42",
254 nmea_info));
256 ok1(nmea_info.engine_noise_level_available);
257 ok1(nmea_info.engine_noise_level == 342);
258 ok1(nmea_info.voltage_available);
259 ok1(equals(nmea_info.voltage, 12.743));
262 static void
263 TestGTAltimeter()
265 NullPort null;
266 Device *device = gt_altimeter_driver.CreateOnPort(dummy_config, null);
267 ok1(device != NULL);
269 NMEAInfo nmea_info;
270 nmea_info.Reset();
271 nmea_info.clock = fixed(1);
273 ok1(device->ParseNMEA("$LK8EX1,99545,149,1,26,5.10*18", nmea_info));
274 ok1(nmea_info.static_pressure_available);
275 ok1(equals(nmea_info.static_pressure.GetHectoPascal(), 995.45));
276 ok1(!nmea_info.pressure_altitude_available);
277 ok1(nmea_info.noncomp_vario_available);
278 ok1(equals(nmea_info.noncomp_vario, 0.01));
279 ok1(nmea_info.temperature_available);
280 ok1(equals(nmea_info.temperature, 26));
281 ok1(!nmea_info.battery_level_available);
282 ok1(nmea_info.voltage_available);
283 ok1(equals(nmea_info.voltage, 5.1));
285 nmea_info.Reset();
286 nmea_info.clock = fixed(1);
288 ok1(device->ParseNMEA("$LK8EX1,999999,149,-123,,1076,*32", nmea_info));
289 ok1(!nmea_info.static_pressure_available);
290 ok1(nmea_info.pressure_altitude_available);
291 ok1(equals(nmea_info.pressure_altitude, 149));
292 ok1(nmea_info.noncomp_vario_available);
293 ok1(equals(nmea_info.noncomp_vario, -1.23));
294 ok1(!nmea_info.temperature_available);
295 ok1(nmea_info.battery_level_available);
296 ok1(equals(nmea_info.battery_level, 76));
297 ok1(!nmea_info.voltage_available);
300 static void
301 TestBlueFly()
303 NullPort null;
304 Device *device = bluefly_driver.CreateOnPort(dummy_config, null);
305 ok1(device != NULL);
307 NMEAInfo nmea_info;
308 nmea_info.Reset();
309 nmea_info.clock = fixed(1);
311 // repeat input to get stable filter output
312 ok1(device->ParseNMEA("PRS 00017CBA", nmea_info));
313 ok1(device->ParseNMEA("PRS 00017CBA", nmea_info));
314 ok1(device->ParseNMEA("PRS 00017CBA", nmea_info));
315 ok1(device->ParseNMEA("PRS 00017CBA", nmea_info));
316 ok1(device->ParseNMEA("PRS 00017CBA", nmea_info));
317 ok1(device->ParseNMEA("PRS 00017CBA", nmea_info));
318 ok1(nmea_info.static_pressure_available);
319 ok1(equals(nmea_info.static_pressure.GetPascal(), 97466));
321 nmea_info.Reset();
322 nmea_info.clock = fixed(1);
324 ok1(device->ParseNMEA("PRS 00017CCA", nmea_info));
325 ok1(device->ParseNMEA("PRS 00017CCA", nmea_info));
326 ok1(device->ParseNMEA("PRS 00017CCA", nmea_info));
327 ok1(device->ParseNMEA("PRS 00017CCA", nmea_info));
328 ok1(device->ParseNMEA("PRS 00017CCA", nmea_info));
329 ok1(device->ParseNMEA("PRS 00017CCA", nmea_info));
330 ok1(nmea_info.static_pressure_available);
331 ok1(equals(nmea_info.static_pressure.GetPascal(), 97482));
333 ok1(device->ParseNMEA("BAT 1068", nmea_info)); //4.2V
334 ok1(nmea_info.battery_level_available);
335 ok1(equals(nmea_info.battery_level, 100.0));
336 ok1(device->ParseNMEA("BAT EFE", nmea_info)); //3.84V
337 ok1(nmea_info.battery_level_available);
338 ok1(equals(nmea_info.battery_level, 50.0));
339 ok1(device->ParseNMEA("BAT ED8", nmea_info)); //3.80V
340 ok1(nmea_info.battery_level_available);
341 ok1(equals(nmea_info.battery_level, 37.0));
343 delete device;
346 static void
347 TestBorgeltB50()
349 NullPort null;
350 Device *device = b50_driver.CreateOnPort(dummy_config, null);
351 ok1(device != NULL);
353 NMEAInfo nmea_info;
354 nmea_info.Reset();
355 nmea_info.clock = fixed(1);
357 ok1(device->ParseNMEA("$PBB50,042,-01.1,1.0,12345,10,1.3,1,-28*75", nmea_info));
358 ok1(nmea_info.airspeed_available);
359 ok1(equals(nmea_info.true_airspeed, 21.60666666666667));
360 ok1(equals(nmea_info.indicated_airspeed, 57.15892189196558));
361 ok1(nmea_info.total_energy_vario_available);
362 ok1(equals(nmea_info.total_energy_vario, -0.5658888888888889));
363 ok1(nmea_info.settings.mac_cready_available);
364 ok1(equals(nmea_info.settings.mac_cready, 0.5144444444444444));
365 ok1(nmea_info.settings.bugs_available);
366 ok1(equals(nmea_info.settings.bugs, 0.9));
367 ok1(nmea_info.settings.ballast_overload_available);
368 ok1(equals(nmea_info.settings.ballast_overload, 1.3));
369 ok1(nmea_info.switch_state.flight_mode == SwitchState::FlightMode::CIRCLING);
370 ok1(nmea_info.temperature_available);
371 ok1(equals(nmea_info.temperature, 245.15));
373 delete device;
376 static void
377 TestCAI302()
379 NullPort null;
380 Device *device = cai302_driver.CreateOnPort(dummy_config, null);
381 ok1(device != NULL);
383 NMEAInfo nmea_info;
384 nmea_info.Reset();
385 nmea_info.clock = fixed(1);
387 ok1(device->ParseNMEA("!w,000,000,0000,500,01287,01020,-0668,191,199,191,000,000,100*44",
388 nmea_info));
389 ok1(nmea_info.airspeed_available);
390 ok1(nmea_info.total_energy_vario_available);
391 ok1(!nmea_info.engine_noise_level_available);
393 ok1(device->ParseNMEA("$PCAID,N,500,0,*14", nmea_info));
394 ok1(nmea_info.engine_noise_level_available);
395 ok1(nmea_info.engine_noise_level == 0);
397 /* pressure altitude enabled (PCAID) */
398 ok1(device->ParseNMEA("$PCAID,N,500,0,*14", nmea_info));
399 ok1(nmea_info.pressure_altitude_available);
400 ok1(between(nmea_info.pressure_altitude, 499, 501));
402 /* ENL */
403 ok1(device->ParseNMEA("$PCAID,N,500,100,*15", nmea_info));
404 ok1(nmea_info.engine_noise_level_available);
405 ok1(nmea_info.engine_noise_level == 100);
407 /* baro altitude enabled */
408 ok1(device->ParseNMEA("!w,000,000,0000,500,01287,01020,-0668,191,199,191,000,000,100*44",
409 nmea_info));
410 ok1(nmea_info.baro_altitude_available);
411 ok1(equals(nmea_info.baro_altitude, 287));
412 ok1(nmea_info.airspeed_available);
413 ok1(equals(nmea_info.true_airspeed, -6.68));
414 ok1(nmea_info.total_energy_vario_available);
415 ok1(equals(nmea_info.total_energy_vario, -0.463));
417 /* PCAID should not override !w */
418 ok1(device->ParseNMEA("$PCAID,N,500,0,*14", nmea_info));
419 ok1(nmea_info.baro_altitude_available);
420 ok1(equals(nmea_info.baro_altitude, 287));
422 /* MC, ballast, bugs */
423 ok1(device->ParseNMEA("!w,0,0,0,0,0,0,0,0,0,0,10,50,90*56", nmea_info));
424 ok1(nmea_info.settings.mac_cready_available);
425 ok1(equals(nmea_info.settings.mac_cready, 0.5144444444444444));
426 ok1(nmea_info.settings.ballast_fraction_available);
427 ok1(equals(nmea_info.settings.ballast_fraction, 0.5));
428 ok1(nmea_info.settings.bugs_available);
429 ok1(equals(nmea_info.settings.bugs, 0.9));
431 delete device;
434 static void
435 TestCProbe()
437 NullPort null;
438 Device *device = c_probe_driver.CreateOnPort(dummy_config, null);
439 ok1(device != NULL);
441 NMEAInfo nmea_info;
442 nmea_info.Reset();
443 nmea_info.clock = fixed(1);
445 ok1(device->ParseNMEA("$PCPROBE,T,FD92,FF93,00D9,FD18,017E,FEDB,0370,0075,00D6,0064,001C,000000,,",
446 nmea_info));
447 ok1(nmea_info.attitude.pitch_angle_available);
448 ok1(equals(nmea_info.attitude.pitch_angle, 25.6034467702));
449 ok1(nmea_info.attitude.bank_angle_available);
450 ok1(equals(nmea_info.attitude.bank_angle, -11.9963939863));
451 ok1(nmea_info.attitude.heading_available);
452 ok1(equals(nmea_info.attitude.heading, 257.0554705429));
453 ok1(nmea_info.acceleration.available);
454 ok1(nmea_info.acceleration.real);
455 ok1(equals(nmea_info.acceleration.g_load, 1.0030817514));
456 ok1(nmea_info.temperature_available);
457 ok1(equals(nmea_info.temperature,
458 Units::ToSysUnit(fixed(11.7), Unit::DEGREES_CELCIUS)));
459 ok1(nmea_info.humidity_available);
460 ok1(equals(nmea_info.humidity, 21.4));
461 ok1(nmea_info.battery_level_available);
462 ok1(equals(nmea_info.battery_level, 100.0));
463 ok1(nmea_info.dyn_pressure_available);
464 ok1(equals(nmea_info.dyn_pressure.GetPascal(), 2.8));
466 delete device;
469 static void
470 TestEye()
472 NullPort null;
473 std::unique_ptr<Device> device(eye_driver.CreateOnPort(dummy_config, null));
474 ok1(device);
476 NMEAInfo nmea_info;
479 nmea_info.Reset();
480 nmea_info.clock = fixed(1);
482 ok1(device->ParseNMEA("$PEYA,1015.5,1020.5,3499,1012.3,265,12,176,+05.4,+15.2,095,1650,+05.1,+3.9*3a",
483 nmea_info));
484 ok1(nmea_info.static_pressure_available);
485 ok1(equals(nmea_info.static_pressure.GetHectoPascal(), 1015.5));
486 ok1(nmea_info.pitot_pressure_available);
487 ok1(equals(nmea_info.pitot_pressure.GetHectoPascal(), 1020.5));
488 ok1(nmea_info.pressure_altitude_available);
489 ok1(equals(nmea_info.pressure_altitude, 3499));
490 ok1(nmea_info.settings.qnh_available);
491 ok1(equals(nmea_info.settings.qnh.GetHectoPascal(), 1012.3));
492 ok1(nmea_info.external_wind_available);
493 ok1(equals(nmea_info.external_wind.bearing, 265));
494 ok1(equals(nmea_info.external_wind.norm,
495 Units::ToSysUnit(fixed(12), Unit::KILOMETER_PER_HOUR)));
496 ok1(nmea_info.airspeed_available);
497 ok1(nmea_info.airspeed_real);
498 ok1(equals(nmea_info.true_airspeed,
499 Units::ToSysUnit(fixed(176), Unit::KILOMETER_PER_HOUR)));
500 ok1(nmea_info.noncomp_vario_available);
501 ok1(equals(nmea_info.noncomp_vario, 5.4));
502 ok1(nmea_info.temperature_available);
503 ok1(equals(nmea_info.temperature,
504 Units::ToSysUnit(fixed(15.2), Unit::DEGREES_CELCIUS)));
505 ok1(nmea_info.humidity_available);
506 ok1(equals(nmea_info.humidity, 95));
509 nmea_info.Reset();
510 nmea_info.clock = fixed(1);
512 ok1(device->ParseNMEA("$PEYI,+110,+020,+135,+130,+140,+0.12,+1.03,+9.81,+12,248,246,+02.3,*16",
513 nmea_info));
514 ok1(nmea_info.attitude.bank_angle_available);
515 ok1(equals(nmea_info.attitude.bank_angle, 110));
516 ok1(nmea_info.attitude.pitch_angle_available);
517 ok1(equals(nmea_info.attitude.pitch_angle, 20));
518 ok1(nmea_info.attitude.heading_available);
519 ok1(equals(nmea_info.attitude.heading, 248));
520 ok1(nmea_info.acceleration.available);
521 ok1(nmea_info.acceleration.real);
522 ok1(equals(nmea_info.acceleration.g_load, 9.864654074));
525 static void
526 TestFlymasterF1()
528 NullPort null;
529 Device *device = flymaster_f1_driver.CreateOnPort(dummy_config, null);
530 ok1(device != NULL);
532 NMEAInfo nmea_info;
533 nmea_info.Reset();
534 nmea_info.clock = fixed(1);
536 ok1(device->ParseNMEA("$VARIO,999.98,-12,12.4,12.7,0,21.3,25.5*66",
537 nmea_info));
538 ok1(!nmea_info.airspeed_available);
539 ok1(nmea_info.total_energy_vario_available);
540 ok1(equals(nmea_info.total_energy_vario, -1.2));
541 ok1(!nmea_info.voltage_available);
542 ok1(nmea_info.temperature_available);
543 ok1(equals(nmea_info.temperature,
544 Units::ToSysUnit(fixed(21.3), Unit::DEGREES_CELCIUS)));
545 ok1(!nmea_info.baro_altitude_available);
546 ok1(!nmea_info.pressure_altitude_available);
547 ok1(nmea_info.static_pressure_available);
548 ok1(equals(nmea_info.static_pressure.GetPascal(), 99998));
550 ok1(device->ParseNMEA("$VARIO,999.98,-12,12.4,12.7,1,21.3,25.5*67",
551 nmea_info));
552 ok1(nmea_info.voltage_available);
553 ok1(equals(nmea_info.voltage, 12.4));
555 ok1(device->ParseNMEA("$VARIO,999.98,-12,12.4,12.7,2,21.3,25.5*64",
556 nmea_info));
557 ok1(nmea_info.voltage_available);
558 ok1(equals(nmea_info.voltage, 12.7));
560 delete device;
563 static void
564 TestFlyNet()
566 NullPort null;
567 Device *device = flynet_driver.CreateOnPort(dummy_config, null);
568 ok1(device != NULL);
570 NMEAInfo nmea_info;
571 nmea_info.Reset();
572 nmea_info.clock = fixed(1);
574 ok1(device->ParseNMEA("_PRS 00017CBA", nmea_info));
575 ok1(nmea_info.static_pressure_available);
576 ok1(equals(nmea_info.static_pressure.GetPascal(), 97466));
578 nmea_info.Reset();
579 nmea_info.clock = fixed(1);
581 ok1(device->ParseNMEA("_PRS 00018BCD", nmea_info));
582 ok1(nmea_info.static_pressure_available);
583 ok1(equals(nmea_info.static_pressure.GetPascal(), 101325));
585 nmea_info.Reset();
586 nmea_info.clock = fixed(1);
588 ok1(device->ParseNMEA("_BAT 0", nmea_info));
589 ok1(nmea_info.battery_level_available);
590 ok1(equals(nmea_info.battery_level, 0));
592 nmea_info.Reset();
593 nmea_info.clock = fixed(1);
595 ok1(device->ParseNMEA("_BAT 7", nmea_info));
596 ok1(nmea_info.battery_level_available);
597 ok1(equals(nmea_info.battery_level, 70));
599 nmea_info.Reset();
600 nmea_info.clock = fixed(1);
602 ok1(device->ParseNMEA("_BAT A", nmea_info));
603 ok1(nmea_info.battery_level_available);
604 ok1(equals(nmea_info.battery_level, 100));
606 delete device;
609 static void
610 TestFlytec()
612 NullPort null;
613 Device *device = flytec_driver.CreateOnPort(dummy_config, null);
614 ok1(device != NULL);
616 NMEAInfo nmea_info;
617 nmea_info.Reset();
618 nmea_info.clock = fixed(1);
620 ok1(device->ParseNMEA("$BRSF,063,-013,-0035,1,193,00351,535,485*33",
621 nmea_info));
622 ok1(nmea_info.airspeed_available);
623 ok1(equals(nmea_info.true_airspeed, 17.5));
625 nmea_info.Reset();
626 nmea_info.clock = fixed(1);
628 ok1(device->ParseNMEA("$VMVABD,1234.5,M,0547.0,M,-0.0,,,MS,63.0,KH,22.4,C*51",
629 nmea_info));
630 ok1(nmea_info.gps_altitude_available);
631 ok1(equals(nmea_info.gps_altitude, 1234.5));
632 ok1(nmea_info.baro_altitude_available);
633 ok1(equals(nmea_info.baro_altitude, 547.0));
634 ok1(nmea_info.airspeed_available);
635 ok1(equals(nmea_info.true_airspeed, 17.5));
636 ok1(nmea_info.temperature_available);
637 ok1(equals(nmea_info.temperature, 295.55));
639 nmea_info.Reset();
640 nmea_info.clock = fixed(1);
642 ok1(device->ParseNMEA("$FLYSEN,,,,,,,,,V,,101450,02341,0334,02000,,,,,,,,,*72",
643 nmea_info));
644 ok1(!nmea_info.date_available);
645 ok1(!nmea_info.time_available);
646 ok1(nmea_info.static_pressure_available);
647 ok1(equals(nmea_info.static_pressure.GetPascal(), 101450));
648 ok1(nmea_info.pressure_altitude_available);
649 ok1(equals(nmea_info.pressure_altitude, 2341));
650 ok1(nmea_info.total_energy_vario_available);
651 ok1(equals(nmea_info.total_energy_vario, 3.34));
652 ok1(nmea_info.airspeed_available);
653 ok1(equals(nmea_info.true_airspeed, 200));
655 nmea_info.Reset();
656 nmea_info.clock = fixed(1);
658 ok1(device->ParseNMEA("$FLYSEN,,,,,,,,,,V,,101450,02341,0334,02000,,,,,,,,,*5e",
659 nmea_info));
660 ok1(!nmea_info.date_available);
661 ok1(!nmea_info.time_available);
662 ok1(nmea_info.static_pressure_available);
663 ok1(equals(nmea_info.static_pressure.GetPascal(), 101450));
664 ok1(nmea_info.pressure_altitude_available);
665 ok1(equals(nmea_info.pressure_altitude, 2341));
666 ok1(nmea_info.total_energy_vario_available);
667 ok1(equals(nmea_info.total_energy_vario, 3.34));
668 ok1(nmea_info.airspeed_available);
669 ok1(equals(nmea_info.true_airspeed, 200));
670 ok1(!nmea_info.battery_level_available);
671 ok1(!nmea_info.temperature_available);
673 ok1(!device->ParseNMEA("$FLYSEN,,,,,,,,,,,,,,,,,,,,*5e", nmea_info));
675 nmea_info.Reset();
676 nmea_info.clock = fixed(1);
678 ok1(device->ParseNMEA("$FLYSEN,241211,201500,4700.840,N,00818.457,E,092,"
679 "01100,01234,A,09,097517,01321,-001,01030,P,023,,038,"
680 "088,00090,00088,800,,*29", nmea_info));
681 ok1(nmea_info.date_available);
682 ok1(nmea_info.date_time_utc.day == 24);
683 ok1(nmea_info.date_time_utc.month == 12);
684 ok1(nmea_info.date_time_utc.year == 2011);
685 ok1(nmea_info.time_available);
686 ok1(nmea_info.date_time_utc.hour == 20);
687 ok1(nmea_info.date_time_utc.minute == 15);
688 ok1(nmea_info.date_time_utc.second == 00);
689 ok1(nmea_info.location_available);
690 ok1(equals(nmea_info.location, 47.014, 8.307616667));
691 ok1(nmea_info.track_available);
692 ok1(equals(nmea_info.track, 92));
693 ok1(nmea_info.ground_speed_available);
694 ok1(equals(nmea_info.ground_speed, 110));
695 ok1(nmea_info.gps_altitude_available);
696 ok1(equals(nmea_info.gps_altitude, 1234));
697 ok1(nmea_info.gps.satellites_used_available);
698 ok1(nmea_info.gps.satellites_used == 9);
699 ok1(nmea_info.static_pressure_available);
700 ok1(equals(nmea_info.static_pressure.GetPascal(), 97517));
701 ok1(nmea_info.pressure_altitude_available);
702 ok1(equals(nmea_info.pressure_altitude, 1321));
703 ok1(nmea_info.total_energy_vario_available);
704 ok1(equals(nmea_info.total_energy_vario, -0.01));
705 ok1(nmea_info.airspeed_available);
706 ok1(equals(nmea_info.true_airspeed, 103));
707 ok1(nmea_info.battery_level_available);
708 ok1(equals(nmea_info.battery_level, (88.0 + 38.0) / 2));
709 ok1(nmea_info.temperature_available);
710 ok1(equals(nmea_info.temperature, Units::ToSysUnit(fixed(23), Unit::DEGREES_CELCIUS)));
712 nmea_info.Reset();
713 nmea_info.clock = fixed(1);
715 ok1(device->ParseNMEA("$FLYSEN,241211,201500,4700.840,N,00818.457,E,092,"
716 "01100,01234,V,09,097517,01321,-001,01030,P,023,017,038,"
717 ",00090,00088,800,,*38", nmea_info));
718 ok1(nmea_info.date_available);
719 ok1(nmea_info.date_time_utc.day == 24);
720 ok1(nmea_info.date_time_utc.month == 12);
721 ok1(nmea_info.date_time_utc.year == 2011);
722 ok1(nmea_info.time_available);
723 ok1(nmea_info.date_time_utc.hour == 20);
724 ok1(nmea_info.date_time_utc.minute == 15);
725 ok1(nmea_info.date_time_utc.second == 00);
726 ok1(!nmea_info.location_available);
727 ok1(!nmea_info.track_available);
728 ok1(!nmea_info.ground_speed_available);
729 ok1(!nmea_info.gps_altitude_available);
730 ok1(nmea_info.gps.satellites_used_available);
731 ok1(nmea_info.gps.satellites_used == 9);
732 ok1(nmea_info.static_pressure_available);
733 ok1(equals(nmea_info.static_pressure.GetPascal(), 97517));
734 ok1(nmea_info.pressure_altitude_available);
735 ok1(equals(nmea_info.pressure_altitude, 1321));
736 ok1(nmea_info.total_energy_vario_available);
737 ok1(equals(nmea_info.total_energy_vario, -0.01));
738 ok1(nmea_info.airspeed_available);
739 ok1(equals(nmea_info.true_airspeed, 103));
740 ok1(nmea_info.battery_level_available);
741 ok1(equals(nmea_info.battery_level, 38.0));
742 ok1(nmea_info.temperature_available);
743 ok1(equals(nmea_info.temperature, Units::ToSysUnit(fixed(17), Unit::DEGREES_CELCIUS)));
745 delete device;
748 static void
749 TestLeonardo()
751 NullPort null;
752 Device *device = leonardo_driver.CreateOnPort(dummy_config, null);
753 ok1(device != NULL);
755 NMEAInfo nmea_info;
756 nmea_info.Reset();
757 nmea_info.clock = fixed(1);
759 ok1(device->ParseNMEA("$C,+2025,-7,+18,+25,+29,122,314,314,0,-356,+25,45,T*3D",
760 nmea_info));
761 ok1(nmea_info.baro_altitude_available);
762 ok1(equals(nmea_info.baro_altitude, 2025));
763 ok1(nmea_info.total_energy_vario_available);
764 ok1(equals(nmea_info.total_energy_vario, -0.07));
765 ok1(nmea_info.airspeed_available);
766 ok1(equals(nmea_info.true_airspeed, 5));
767 ok1(nmea_info.netto_vario_available);
768 ok1(equals(nmea_info.netto_vario, 2.5));
770 ok1(nmea_info.temperature_available);
771 ok1(equals(nmea_info.temperature, 302.15));
773 ok1(nmea_info.external_wind_available);
774 ok1(equals(nmea_info.external_wind.bearing, 45));
775 ok1(equals(nmea_info.external_wind.norm, 6.94444444));
777 nmea_info.Reset();
778 nmea_info.clock = fixed(1);
780 ok1(device->ParseNMEA("$c,+2025,-2,+18*5C", nmea_info));
781 ok1(nmea_info.baro_altitude_available);
782 ok1(equals(nmea_info.baro_altitude, 2025));
783 ok1(nmea_info.total_energy_vario_available);
784 ok1(equals(nmea_info.total_energy_vario, -0.02));
785 ok1(nmea_info.airspeed_available);
786 ok1(equals(nmea_info.true_airspeed,
787 Units::ToSysUnit(fixed(18), Unit::KILOMETER_PER_HOUR)));
788 ok1(!nmea_info.netto_vario_available);
790 nmea_info.Reset();
791 nmea_info.clock = fixed(1);
793 ok1(device->ParseNMEA("$D,+7,100554,+25,18,+31,,0,-356,+25,+11,115,96*6A",
794 nmea_info));
795 ok1(nmea_info.total_energy_vario_available);
796 ok1(equals(nmea_info.total_energy_vario, 0.7));
797 ok1(nmea_info.static_pressure_available);
798 ok1(equals(nmea_info.static_pressure.GetHectoPascal(), 1005.54));
799 ok1(nmea_info.netto_vario_available);
800 ok1(equals(nmea_info.netto_vario, 2.5));
801 ok1(nmea_info.airspeed_available);
802 ok1(equals(nmea_info.true_airspeed, 5));
803 ok1(nmea_info.temperature_available);
804 ok1(equals(nmea_info.temperature, 304.15));
806 nmea_info.Reset();
807 nmea_info.clock = fixed(1);
809 ok1(device->ParseNMEA("$PDGFTL1,2025,2000,250,-14,45,134,28,65,382,153*3D",
810 nmea_info));
811 ok1(nmea_info.pressure_altitude_available);
812 ok1(equals(nmea_info.pressure_altitude, 2025));
813 ok1(nmea_info.baro_altitude_available);
814 ok1(equals(nmea_info.baro_altitude, 2000));
815 ok1(nmea_info.total_energy_vario_available);
816 ok1(equals(nmea_info.total_energy_vario, 2.5));
817 ok1(nmea_info.netto_vario_available);
818 ok1(equals(nmea_info.netto_vario, -1.4));
819 ok1(nmea_info.airspeed_available);
820 ok1(nmea_info.airspeed_real);
821 ok1(equals(nmea_info.indicated_airspeed,
822 Units::ToSysUnit(fixed(45), Unit::KILOMETER_PER_HOUR)));
823 ok1(nmea_info.external_wind_available);
824 ok1(equals(nmea_info.external_wind.bearing, 65));
825 ok1(equals(nmea_info.external_wind.norm, 7.777777));
826 ok1(nmea_info.voltage_available);
827 ok1(equals(nmea_info.voltage, 3.82));
829 nmea_info.Reset();
830 nmea_info.clock = fixed(1);
832 ok1(device->ParseNMEA("$PDGFTTL,2025,2000,250,-14*41", nmea_info));
833 ok1(nmea_info.pressure_altitude_available);
834 ok1(equals(nmea_info.pressure_altitude, 2025));
835 ok1(nmea_info.baro_altitude_available);
836 ok1(equals(nmea_info.baro_altitude, 2000));
837 ok1(nmea_info.total_energy_vario_available);
838 ok1(equals(nmea_info.total_energy_vario, 2.5));
839 ok1(nmea_info.netto_vario_available);
840 ok1(equals(nmea_info.netto_vario, -1.4));
842 delete device;
845 static void
846 TestLevilAHRS()
848 NullPort null;
849 Device *device = levil_driver.CreateOnPort(dummy_config, null);
850 ok1(device != NULL);
852 NMEAInfo nmea_info;
853 nmea_info.Reset();
854 nmea_info.clock = fixed(1);
856 // All angles in tenth of degrees
857 ok1(device->ParseNMEA("$RPYL,127,729,3215,99,88,1376,0,", nmea_info));
858 ok1(nmea_info.attitude.bank_angle_available);
859 ok1(equals(nmea_info.attitude.bank_angle, 12.7));
860 ok1(nmea_info.attitude.pitch_angle_available);
861 ok1(equals(nmea_info.attitude.pitch_angle, 72.9));
862 ok1(nmea_info.attitude.heading_available);
863 ok1(equals(nmea_info.attitude.heading, 321.5));
864 ok1(nmea_info.acceleration.available);
865 ok1(nmea_info.acceleration.real);
866 ok1(equals(nmea_info.acceleration.g_load, 1.376));
868 // speed in kn, alt in ft, vs in ft/min
869 ok1(device->ParseNMEA("$APENV1,94,1500,0,0,0,0,", nmea_info));
870 ok1(nmea_info.airspeed_available);
871 ok1(equals(nmea_info.indicated_airspeed, 48.357777777));
872 ok1(nmea_info.pressure_altitude_available);
873 ok1(equals(nmea_info.pressure_altitude, 457.2));
874 // vertical speed not implemented
876 delete device;
880 static void
881 TestLX(const struct DeviceRegister &driver, bool condor=false)
883 NullPort null;
884 Device *device = driver.CreateOnPort(dummy_config, null);
885 ok1(device != NULL);
887 NMEAInfo nmea_info;
888 nmea_info.Reset();
889 nmea_info.clock = fixed(1);
891 /* empty sentence */
892 ok1(device->ParseNMEA("$LXWP0,N,,,,,,,,,,,*6d", nmea_info));
893 ok1(!nmea_info.pressure_altitude_available);
894 ok1(!nmea_info.baro_altitude_available);
895 ok1(!nmea_info.airspeed_available);
896 ok1(!nmea_info.total_energy_vario_available);
897 ok1(!nmea_info.external_wind_available);
900 nmea_info.Reset();
901 nmea_info.clock = fixed(1);
903 /* altitude and wind */
904 ok1(device->ParseNMEA("$LXWP0,N,,1266.5,,,,,,,,248,23.1*55", nmea_info));
906 if (condor) {
907 ok1(!nmea_info.pressure_altitude_available);
908 ok1(nmea_info.baro_altitude_available);
909 ok1(equals(nmea_info.baro_altitude, 1266.5));
910 } else {
911 ok1(nmea_info.pressure_altitude_available);
912 ok1(!nmea_info.baro_altitude_available);
913 ok1(equals(nmea_info.pressure_altitude, 1266.5));
916 ok1(!nmea_info.airspeed_available);
917 ok1(!nmea_info.total_energy_vario_available);
919 ok1(nmea_info.external_wind_available);
920 ok1(equals(nmea_info.external_wind.norm, 23.1 / 3.6));
921 ok1(equals(nmea_info.external_wind.bearing, condor ? 68 : 248));
924 nmea_info.Reset();
925 nmea_info.clock = fixed(1);
927 /* airspeed and vario available */
928 ok1(device->ParseNMEA("$LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1*47",
929 nmea_info));
930 ok1((bool)nmea_info.pressure_altitude_available == !condor);
931 ok1((bool)nmea_info.baro_altitude_available == condor);
932 ok1(equals(condor ? nmea_info.baro_altitude : nmea_info.pressure_altitude,
933 1665.5));
934 ok1(nmea_info.airspeed_available);
935 ok1(equals(nmea_info.true_airspeed, 222.3/3.6));
936 ok1(nmea_info.total_energy_vario_available);
937 ok1(equals(nmea_info.total_energy_vario, 1.71));
939 ok1(nmea_info.external_wind_available);
940 ok1(equals(nmea_info.external_wind.norm, 10.1 / 3.6));
941 ok1(equals(nmea_info.external_wind.bearing, condor ? 354 : 174));
944 nmea_info.Reset();
945 nmea_info.clock = fixed(1);
947 /* airspeed without altitude */
948 ok1(device->ParseNMEA("$LXWP0,Y,222.3,,,,,,,,,,*55",
949 nmea_info));
950 ok1(!nmea_info.pressure_altitude_available);
951 ok1(!nmea_info.baro_altitude_available);
952 // TODO: indicated airspeed shouldn't be available without altitude
953 ok1(nmea_info.airspeed_available);
954 ok1(equals(nmea_info.true_airspeed, 222.3/3.6));
955 ok1(equals(nmea_info.indicated_airspeed, 222.3/3.6));
958 if (!condor) {
959 ok1(device->ParseNMEA("$LXWP2,1.7,1.1,5,,,,*3e", nmea_info));
960 ok1(nmea_info.settings.mac_cready_available);
961 ok1(equals(nmea_info.settings.mac_cready, 1.7));
962 ok1(nmea_info.settings.ballast_overload_available);
963 ok1(equals(nmea_info.settings.ballast_overload, 1.1));
964 ok1(nmea_info.settings.bugs_available);
965 ok1(equals(nmea_info.settings.bugs, 0.95));
966 ok1(!nmea_info.settings.volume_available);
968 ok1(device->ParseNMEA("$LXWP2,,,,,,,76*0c", nmea_info));
969 ok1(nmea_info.settings.volume_available);
970 ok1(nmea_info.settings.volume == 76);
973 nmea_info.Reset();
974 nmea_info.clock = fixed(1);
976 // Test LX160 (sw 3.04) variant (different bugs notation)
977 ok1(device->ParseNMEA("$LXWP2,1.1,1.00,1.00,2.14,-3.87,2.38*3E", nmea_info));
978 ok1(nmea_info.settings.mac_cready_available);
979 ok1(equals(nmea_info.settings.mac_cready, 1.1));
980 ok1(nmea_info.settings.ballast_overload_available);
981 ok1(equals(nmea_info.settings.ballast_overload, 1.0));
982 ok1(nmea_info.settings.bugs_available);
983 ok1(equals(nmea_info.settings.bugs, 1.0));
984 ok1(!nmea_info.settings.volume_available);
986 ok1(device->ParseNMEA("$LXWP2,1.1,1.50,1.10,1.83,-3.87,2.91*34", nmea_info));
987 ok1(nmea_info.settings.mac_cready_available);
988 ok1(equals(nmea_info.settings.mac_cready, 1.1));
989 ok1(nmea_info.settings.ballast_overload_available);
990 ok1(equals(nmea_info.settings.ballast_overload, 1.5));
991 ok1(nmea_info.settings.bugs_available);
992 ok1(equals(nmea_info.settings.bugs, 0.9));
993 ok1(!nmea_info.settings.volume_available);
995 ok1(device->ParseNMEA("$LXWP2,0.0,1.20,1.05,2.00,-3.87,2.61*30", nmea_info));
996 ok1(nmea_info.settings.mac_cready_available);
997 ok1(equals(nmea_info.settings.mac_cready, 0.0));
998 ok1(nmea_info.settings.ballast_overload_available);
999 ok1(equals(nmea_info.settings.ballast_overload, 1.2));
1000 ok1(nmea_info.settings.bugs_available);
1001 ok1(equals(nmea_info.settings.bugs, 0.95));
1002 ok1(!nmea_info.settings.volume_available);
1004 ok1(device->ParseNMEA("$LXWP2,1.5,1.00,2.5,2.14,-3.87,2.38*0C", nmea_info));
1005 ok1(nmea_info.settings.mac_cready_available);
1006 ok1(equals(nmea_info.settings.mac_cready, 1.5));
1007 ok1(nmea_info.settings.ballast_overload_available);
1008 ok1(equals(nmea_info.settings.ballast_overload, 1.0));
1009 ok1(nmea_info.settings.bugs_available);
1010 ok1(equals(nmea_info.settings.bugs, 0.975));
1011 ok1(!nmea_info.settings.volume_available);
1014 nmea_info.Reset();
1015 nmea_info.clock = fixed(1);
1017 LXDevice &lx_device = *(LXDevice *)device;
1018 ok1(!lx_device.IsV7());
1019 ok1(!lx_device.IsNano());
1020 ok1(!lx_device.IsLX16xx());
1022 lx_device.ResetDeviceDetection();
1023 ok1(device->ParseNMEA("$LXWP1,V7,12345,1.0,1.0,12345*6f", nmea_info));
1024 ok1(lx_device.IsV7());
1025 ok1(!lx_device.IsNano());
1026 ok1(!lx_device.IsLX16xx());
1028 lx_device.ResetDeviceDetection();
1029 ok1(device->ParseNMEA("$LXWP1,NANO,12345,1.0,1.0,12345*00", nmea_info));
1030 ok1(!lx_device.IsV7());
1031 ok1(lx_device.IsNano());
1032 ok1(!lx_device.IsLX16xx());
1034 lx_device.ResetDeviceDetection();
1035 ok1(device->ParseNMEA("$LXWP1,1606,4294967295,1.90,1.00,4294967295*06", nmea_info));
1036 ok1(!lx_device.IsV7());
1037 ok1(!lx_device.IsNano());
1038 ok1(lx_device.IsLX16xx());
1040 ok1(nmea_info.device.product == "1606");
1041 ok1(nmea_info.device.serial == "4294967295");
1042 ok1(nmea_info.device.software_version == "1.90");
1043 ok1(nmea_info.device.hardware_version == "1.00");
1046 ok1(device->ParseNMEA("$LXWP3,47.76,0,2.0,5.0,15,30,2.5,1.0,0,100,0.1,,0*08", nmea_info));
1047 ok1(nmea_info.settings.qnh_available);
1048 ok1(equals(nmea_info.settings.qnh.GetHectoPascal(), 1015));
1051 delete device;
1054 static void
1055 TestLXV7()
1057 NullPort null;
1058 Device *device = lx_driver.CreateOnPort(dummy_config, null);
1059 ok1(device != NULL);
1061 NMEAInfo basic;
1062 basic.Reset();
1063 basic.clock = fixed(1);
1065 LXDevice &lx_device = *(LXDevice *)device;
1066 lx_device.ResetDeviceDetection();
1068 ok1(device->ParseNMEA("$PLXVF,,1.00,0.87,-0.12,-0.25,90.2,244.3,*64", basic));
1069 ok1(basic.netto_vario_available);
1070 ok1(equals(basic.netto_vario, -0.25));
1071 ok1(basic.airspeed_available);
1072 ok1(equals(basic.indicated_airspeed, 90.2));
1073 ok1(basic.pressure_altitude_available);
1074 ok1(equals(basic.pressure_altitude, 244.3));
1076 ok1(lx_device.IsV7());
1077 lx_device.ResetDeviceDetection();
1079 ok1(device->ParseNMEA("$PLXVS,23.1,0,12.3,*71", basic));
1080 ok1(basic.temperature_available);
1081 ok1(equals(basic.temperature, 296.25));
1082 ok1(basic.switch_state.flight_mode == SwitchState::FlightMode::CIRCLING);
1083 ok1(basic.voltage_available);
1084 ok1(equals(basic.voltage, 12.3));
1086 ok1(lx_device.IsV7());
1088 delete device;
1091 static void
1092 TestILEC()
1094 NullPort null;
1095 Device *device = ilec_driver.CreateOnPort(dummy_config, null);
1096 ok1(device != NULL);
1098 NMEAInfo nmea_info;
1099 nmea_info.Reset();
1100 nmea_info.clock = fixed(1);
1102 /* baro altitude disabled */
1103 ok1(device->ParseNMEA("$PILC,PDA1,1489,-3.21*69", nmea_info));
1104 ok1(!nmea_info.airspeed_available);
1105 ok1(nmea_info.total_energy_vario_available);
1106 ok1(equals(nmea_info.total_energy_vario, -3.21));
1107 ok1(!nmea_info.external_wind_available);
1109 /* baro altitude enabled */
1110 ok1(device->ParseNMEA("$PILC,PDA1,1489,-3.21,274,15,58*7D", nmea_info));
1111 ok1(nmea_info.baro_altitude_available);
1112 ok1(equals(nmea_info.baro_altitude, 1489));
1113 ok1(nmea_info.total_energy_vario_available);
1114 ok1(equals(nmea_info.total_energy_vario, -3.21));
1115 ok1(nmea_info.external_wind_available);
1116 ok1(equals(nmea_info.external_wind.norm, 15 / 3.6));
1117 ok1(equals(nmea_info.external_wind.bearing, 274));
1119 delete device;
1122 static void
1123 TestVega()
1125 NullPort null;
1126 Device *device = vega_driver.CreateOnPort(dummy_config, null);
1127 ok1(device != NULL);
1129 NMEAInfo nmea_info;
1130 nmea_info.Reset();
1131 nmea_info.clock = fixed(1);
1133 /* enable FLARM mode (switches the $PGRMZ parser to pressure
1134 altitude) */
1135 NMEAParser parser;
1136 ok1(parser.ParseLine("$PFLAU,0,0,0,1,0,,0,,*63", nmea_info));
1137 ok1(parser.ParseLine("$PGRMZ,2447,F,2*0F", nmea_info));
1138 ok1(nmea_info.pressure_altitude_available);
1139 ok1(equals(nmea_info.pressure_altitude, 745.845));
1141 ok1(device->ParseNMEA("$PDSWC,0,1002000,100,115*54", nmea_info));
1142 ok1(nmea_info.settings.mac_cready_available);
1143 ok1(equals(nmea_info.settings.mac_cready, 0));
1144 ok1(nmea_info.voltage_available);
1145 ok1(equals(nmea_info.voltage, 11.5));
1147 ok1(device->ParseNMEA("$PDVDV,1,0,1062,762,9252,0*5B", nmea_info));
1148 ok1(nmea_info.total_energy_vario_available);
1149 ok1(equals(nmea_info.total_energy_vario, 0.1));
1150 ok1(nmea_info.airspeed_available);
1151 ok1(equals(nmea_info.true_airspeed, 0));
1152 ok1(equals(nmea_info.indicated_airspeed, 0));
1153 ok1(!nmea_info.static_pressure_available);
1154 ok1(!nmea_info.baro_altitude_available);
1155 ok1(nmea_info.pressure_altitude_available);
1156 ok1(equals(nmea_info.pressure_altitude, 762));
1158 /* parse $PGRMZ again, it should be ignored */
1159 ok1(parser.ParseLine("$PGRMZ,2447,F,2*0F", nmea_info));
1160 ok1(nmea_info.pressure_altitude_available);
1161 ok1(equals(nmea_info.pressure_altitude, 762));
1163 delete device;
1166 static void
1167 TestWesterboer()
1169 NullPort null;
1170 Device *device = westerboer_driver.CreateOnPort(dummy_config, null);
1171 ok1(device != NULL);
1173 NMEAInfo nmea_info;
1174 nmea_info.Reset();
1175 nmea_info.clock = fixed(1);
1177 ok1(device->ParseNMEA("$PWES0,20,-25,25,-22,2,-100,589,589,1260,1296,128,295*01",
1178 nmea_info));
1179 ok1(nmea_info.baro_altitude_available);
1180 ok1(equals(nmea_info.baro_altitude, 589));
1181 ok1(nmea_info.total_energy_vario_available);
1182 ok1(equals(nmea_info.total_energy_vario, -2.5));
1183 ok1(nmea_info.netto_vario_available);
1184 ok1(equals(nmea_info.netto_vario, -2.2));
1185 ok1(nmea_info.airspeed_available);
1186 ok1(equals(nmea_info.indicated_airspeed, 35));
1187 ok1(equals(nmea_info.true_airspeed, 36));
1188 ok1(nmea_info.voltage_available);
1189 ok1(equals(nmea_info.voltage, 12.8));
1190 ok1(nmea_info.temperature_available);
1191 ok1(equals(nmea_info.temperature, 29.5 + 273.15));
1193 ok1(device->ParseNMEA("$PWES1,20,21,0,030,1,6,385,10*1a", nmea_info));
1194 ok1(nmea_info.settings.mac_cready_available);
1195 ok1(equals(nmea_info.settings.mac_cready, 2.1));
1196 ok1(nmea_info.settings.wing_loading_available);
1197 ok1(equals(nmea_info.settings.wing_loading, 38.5));
1198 ok1(nmea_info.settings.bugs_available);
1199 ok1(equals(nmea_info.settings.bugs, 0.9));
1201 delete device;
1204 static void
1205 TestZander()
1207 NullPort null;
1208 Device *device = zander_driver.CreateOnPort(dummy_config, null);
1209 ok1(device != NULL);
1211 NMEAInfo nmea_info;
1212 nmea_info.Reset();
1213 nmea_info.clock = fixed(1);
1215 /* baro altitude enabled */
1216 ok1(device->ParseNMEA("$PZAN1,02476,123456*04", nmea_info));
1217 ok1(nmea_info.baro_altitude_available);
1218 ok1(equals(nmea_info.baro_altitude, 2476));
1220 ok1(device->ParseNMEA("$PZAN2,123,9850*03", nmea_info));
1221 ok1(nmea_info.airspeed_available);
1222 ok1(equals(nmea_info.true_airspeed, fixed(34.1667)));
1223 ok1(nmea_info.total_energy_vario_available);
1224 ok1(equals(nmea_info.total_energy_vario, fixed(-1.5)));
1226 nmea_info.Reset();
1227 nmea_info.clock = fixed(1);
1228 ok1(device->ParseNMEA("$PZAN3,+,026,V,321,035,A,321,035,V*44", nmea_info));
1229 ok1(nmea_info.external_wind_available);
1230 ok1(equals(nmea_info.external_wind.bearing, 321));
1231 ok1(equals(nmea_info.external_wind.norm, 9.72222));
1233 nmea_info.Reset();
1234 nmea_info.clock = fixed(1);
1235 ok1(device->ParseNMEA("$PZAN3,+,026,V,321,035,V,321,035,V*53", nmea_info));
1236 ok1(!nmea_info.external_wind_available);
1238 nmea_info.Reset();
1239 nmea_info.clock = fixed(1);
1240 ok1(device->ParseNMEA("$PZAN3,+,026,A,321,035,A*2f", nmea_info));
1241 ok1(nmea_info.external_wind_available);
1242 ok1(equals(nmea_info.external_wind.bearing, 321));
1243 ok1(equals(nmea_info.external_wind.norm, 9.72222));
1245 nmea_info.Reset();
1246 nmea_info.clock = fixed(1);
1247 ok1(device->ParseNMEA("$PZAN3,+,026,A,321,035,A,V*55", nmea_info));
1248 ok1(nmea_info.external_wind_available);
1249 ok1(equals(nmea_info.external_wind.bearing, 321));
1250 ok1(equals(nmea_info.external_wind.norm, 9.72222));
1252 nmea_info.Reset();
1253 nmea_info.clock = fixed(1);
1254 ok1(device->ParseNMEA("$PZAN3,+,026,A,321,035,V,A*55", nmea_info));
1255 ok1(nmea_info.external_wind_available);
1256 ok1(equals(nmea_info.external_wind.bearing, 321));
1257 ok1(equals(nmea_info.external_wind.norm, 9.72222));
1259 nmea_info.Reset();
1260 nmea_info.clock = fixed(1);
1261 ok1(device->ParseNMEA("$PZAN3,+,026,A,321,035,A,A*42", nmea_info));
1262 ok1(nmea_info.external_wind_available);
1263 ok1(equals(nmea_info.external_wind.bearing, 321));
1264 ok1(equals(nmea_info.external_wind.norm, 9.72222));
1266 nmea_info.Reset();
1267 nmea_info.clock = fixed(1);
1268 ok1(device->ParseNMEA("$PZAN3,+,026,A,321,035,V*38", nmea_info));
1269 ok1(!nmea_info.external_wind_available);
1271 nmea_info.Reset();
1272 nmea_info.clock = fixed(1);
1273 ok1(device->ParseNMEA("$PZAN3,+,026,A,321,035,V,V*42", nmea_info));
1274 ok1(!nmea_info.external_wind_available);
1276 ok1(device->ParseNMEA("$PZAN4,1.5,+,20,39,45*15", nmea_info));
1277 ok1(nmea_info.settings.mac_cready_available);
1278 ok1(equals(nmea_info.settings.mac_cready, 1.5));
1280 nmea_info.Reset();
1281 nmea_info.clock = fixed(1);
1282 ok1(device->ParseNMEA("$PZAN5,,MUEHL,123.4,KM,T,234*24", nmea_info));
1283 ok1(nmea_info.switch_state.flight_mode == SwitchState::FlightMode::UNKNOWN);
1285 nmea_info.Reset();
1286 nmea_info.clock = fixed(1);
1287 ok1(device->ParseNMEA("$PZAN5,SF,MUEHL,123.4,KM,T,234*31", nmea_info));
1288 ok1(nmea_info.switch_state.flight_mode == SwitchState::FlightMode::CRUISE);
1290 nmea_info.Reset();
1291 nmea_info.clock = fixed(1);
1292 ok1(device->ParseNMEA("$PZAN5,VA,MUEHL,123.4,KM,T,234*33", nmea_info));
1293 ok1(nmea_info.switch_state.flight_mode == SwitchState::FlightMode::CIRCLING);
1295 delete device;
1298 static void
1299 TestDeclare(const struct DeviceRegister &driver)
1301 FaultInjectionPort port(*(DataHandler *)NULL);
1302 Device *device = driver.CreateOnPort(dummy_config, port);
1303 ok1(device != NULL);
1305 LoggerSettings logger_settings;
1306 logger_settings.pilot_name = _T("Foo Bar");
1307 Plane plane;
1308 plane.registration = _T("D-3003");
1309 plane.competition_id = _T("33");
1310 plane.type = _T("Cirrus");
1312 Declaration declaration(logger_settings, plane, NULL);
1313 const GeoPoint gp(Angle::Degrees(7.7061111111111114),
1314 Angle::Degrees(51.051944444444445));
1315 Waypoint wp(gp);
1316 wp.name = _T("Foo");
1317 wp.elevation = fixed(123);
1318 declaration.Append(wp);
1319 declaration.Append(wp);
1320 declaration.Append(wp);
1321 declaration.Append(wp);
1323 NullOperationEnvironment env;
1325 for (unsigned i = 0; i < 1024; ++i) {
1326 inject_port_fault = i;
1327 bool success = device->Declare(declaration, NULL, env);
1328 if (success || !port.running ||
1329 port.baud_rate != FaultInjectionPort::DEFAULT_BAUD_RATE)
1330 break;
1333 device->EnableNMEA(env);
1335 ok1(port.baud_rate == FaultInjectionPort::DEFAULT_BAUD_RATE);
1337 delete device;
1340 static void
1341 TestFlightList(const struct DeviceRegister &driver)
1343 FaultInjectionPort port(*(DataHandler *)NULL);
1344 Device *device = driver.CreateOnPort(dummy_config, port);
1345 ok1(device != NULL);
1347 NullOperationEnvironment env;
1349 for (unsigned i = 0; i < 1024; ++i) {
1350 inject_port_fault = i;
1351 RecordedFlightList flight_list;
1352 bool success = device->ReadFlightList(flight_list, env);
1353 if (success || !port.running ||
1354 port.baud_rate != FaultInjectionPort::DEFAULT_BAUD_RATE)
1355 break;
1358 device->EnableNMEA(env);
1360 ok1(port.baud_rate == FaultInjectionPort::DEFAULT_BAUD_RATE);
1362 delete device;
1365 int main(int argc, char **argv)
1367 plan_tests(724);
1369 TestGeneric();
1370 TestTasman();
1371 TestFLARM();
1372 TestAltairRU();
1373 TestGTAltimeter();
1374 TestBlueFly();
1375 TestBorgeltB50();
1376 TestCAI302();
1377 TestCProbe();
1378 TestEye();
1379 TestFlymasterF1();
1380 TestFlytec();
1381 TestLeonardo();
1382 TestLevilAHRS();
1383 TestLX(lx_driver);
1384 TestLX(condor_driver, true);
1385 TestLXV7();
1386 TestILEC();
1387 TestVega();
1388 TestWesterboer();
1389 TestZander();
1390 TestFlyNet();
1392 /* XXX the Triadis drivers have too many dependencies, not enabling
1393 for now */
1394 //TestDeclare(altair_pro_driver);
1395 TestDeclare(cai302_driver);
1396 TestDeclare(ew_driver);
1397 TestDeclare(ew_microrecorder_driver);
1398 TestDeclare(posigraph_driver);
1399 TestDeclare(lx_driver);
1400 TestDeclare(imi_driver);
1401 TestDeclare(flarm_driver);
1402 //TestDeclare(vega_driver);
1404 /* XXX Volkslogger doesn't do well with this test case */
1405 //TestDeclare(volkslogger_driver);
1407 TestFlightList(cai302_driver);
1408 TestFlightList(lx_driver);
1409 TestFlightList(imi_driver);
1411 return exit_status();