MockLink.cc 53.9 KB
Newer Older
1
2
3
4
5
6
7
8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
9

Don Gagne's avatar
Don Gagne committed
10
11

#include "MockLink.h"
12
#include "QGCLoggingCategory.h"
13
#include "QGCApplication.h"
14
15

#ifdef UNITTEST_BUILD
DonLakeFlyer's avatar
DonLakeFlyer committed
16
#include "UnitTest.h"
17
#endif
Don Gagne's avatar
Don Gagne committed
18
19
20
21
22
23
24

#include <QTimer>
#include <QDebug>
#include <QFile>

#include <string.h>

25
26
// FIXME: Hack to work around clean headers
#include "FirmwarePlugin/PX4/px4_custom_mode.h"
Daniel Agar's avatar
Daniel Agar committed
27

28
QGC_LOGGING_CATEGORY(MockLinkLog, "MockLinkLog")
Don Gagne's avatar
Don Gagne committed
29
QGC_LOGGING_CATEGORY(MockLinkVerboseLog, "MockLinkVerboseLog")
30

Don Gagne's avatar
Don Gagne committed
31
32
33
34
35
/// @file
///     @brief Mock implementation of a Link.
///
///     @author Don Gagne <don@thegagnes.com>

36
37
// Vehicle position is set close to default Gazebo vehicle location. This allows for multi-vehicle
// testing of a gazebo vehicle and a mocklink vehicle
DonLakeFlyer's avatar
DonLakeFlyer committed
38
39
40
41
42
43
44
45
46
#if 1
double      MockLink::_defaultVehicleLatitude =     47.397;
double      MockLink::_defaultVehicleLongitude =    8.5455;
double      MockLink::_defaultVehicleAltitude =     488.056;
#else
double      MockLink::_defaultVehicleLatitude =     47.6333022928789;
double      MockLink::_defaultVehicleLongitude =    -122.08833157994995;
double      MockLink::_defaultVehicleAltitude =     19.0;
#endif
47
48
int         MockLink::_nextVehicleSystemId =        128;
const char* MockLink::_failParam =                  "COM_FLTMODE6";
Don Gagne's avatar
Don Gagne committed
49

50
const char* MockConfiguration::_firmwareTypeKey =   "FirmwareType";
51
const char* MockConfiguration::_vehicleTypeKey =    "VehicleType";
52
const char* MockConfiguration::_sendStatusTextKey = "SendStatusText";
Don Gagne's avatar
Don Gagne committed
53
const char* MockConfiguration::_highLatencyKey =    "HighLatency";
Don Gagne's avatar
Don Gagne committed
54
const char* MockConfiguration::_failureModeKey =    "FailureMode";
Don Gagne's avatar
Don Gagne committed
55

56
MockLink::MockLink(SharedLinkConfigurationPointer& config)
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    : LinkInterface                         (config)
    , _missionItemHandler                   (this, qgcApp()->toolbox()->mavlinkProtocol())
    , _name                                 ("MockLink")
    , _connected                            (false)
    , _mavlinkChannel                       (0)
    , _vehicleSystemId                      (_nextVehicleSystemId++)
    , _vehicleComponentId                   (MAV_COMP_ID_AUTOPILOT1)
    , _inNSH                                (false)
    , _mavlinkStarted                       (true)
    , _mavBaseMode                          (MAV_MODE_FLAG_MANUAL_INPUT_ENABLED | MAV_MODE_FLAG_CUSTOM_MODE_ENABLED)
    , _mavState                             (MAV_STATE_STANDBY)
    , _firmwareType                         (MAV_AUTOPILOT_PX4)
    , _vehicleType                          (MAV_TYPE_QUADROTOR)
    , _vehicleLatitude                      (_defaultVehicleLatitude + ((_vehicleSystemId - 128) * 0.0001))     // Slight offset for each vehicle
    , _vehicleLongitude                     (_defaultVehicleLongitude + ((_vehicleSystemId - 128) * 0.0001))
    , _vehicleAltitude                      (_defaultVehicleAltitude)
murata's avatar
murata committed
73
    , _fileServer                           (nullptr)
74
75
76
77
78
    , _sendStatusText                       (false)
    , _apmSendHomePositionOnEmptyList       (false)
    , _failureMode                          (MockConfiguration::FailNone)
    , _sendHomePositionDelayCount           (10)    // No home position for 4 seconds
    , _sendGPSPositionDelayCount            (100)   // No gps lock for 5 seconds
Don Gagne's avatar
Don Gagne committed
79
    , _currentParamRequestListComponentIndex(-1)
80
81
82
    , _currentParamRequestListParamIndex    (-1)
    , _logDownloadCurrentOffset             (0)
    , _logDownloadBytesRemaining            (0)
83
    , _adsbAngle                            (0)
Don Gagne's avatar
Don Gagne committed
84
{
85
86
87
88
    MockConfiguration* mockConfig = qobject_cast<MockConfiguration*>(_config.data());
    _firmwareType = mockConfig->firmwareType();
    _vehicleType = mockConfig->vehicleType();
    _sendStatusText = mockConfig->sendStatusText();
Don Gagne's avatar
Don Gagne committed
89
    _highLatency = mockConfig->highLatency();
90
    _failureMode = mockConfig->failureMode();
Don Gagne's avatar
Don Gagne committed
91

Don Gagne's avatar
Don Gagne committed
92
93
94
95
96
97
    union px4_custom_mode   px4_cm;

    px4_cm.data = 0;
    px4_cm.main_mode = PX4_CUSTOM_MAIN_MODE_MANUAL;
    _mavCustomMode = px4_cm.data;

Don Gagne's avatar
Don Gagne committed
98
99
    _fileServer = new MockLinkFileServer(_vehicleSystemId, _vehicleComponentId, this);
    Q_CHECK_PTR(_fileServer);
dogmaphobic's avatar
dogmaphobic committed
100

Don Gagne's avatar
Don Gagne committed
101
    moveToThread(this);
dogmaphobic's avatar
dogmaphobic committed
102

Don Gagne's avatar
Don Gagne committed
103
    _loadParams();
104
105
106

    _adsbVehicleCoordinate = QGeoCoordinate(_vehicleLatitude, _vehicleLongitude).atDistanceAndAzimuth(1000, _adsbAngle);
    _adsbVehicleCoordinate.setAltitude(100);
Gus Grubba's avatar
Gus Grubba committed
107
    _runningTime.start();
Don Gagne's avatar
Don Gagne committed
108
109
110
111
}

MockLink::~MockLink(void)
{
112
    _disconnect();
113
114
115
    if (!_logDownloadFilename.isEmpty()) {
        QFile::remove(_logDownloadFilename);
    }
Don Gagne's avatar
Don Gagne committed
116
117
}

118
bool MockLink::_connect(void)
Don Gagne's avatar
Don Gagne committed
119
{
120
121
    if (!_connected) {
        _connected = true;
Don Gagne's avatar
Don Gagne committed
122
123
124
125
126
127
128
129
        _mavlinkChannel = qgcApp()->toolbox()->linkManager()->_reserveMavlinkChannel();
        if (_mavlinkChannel == 0) {
            qWarning() << "No mavlink channels available";
            return false;
        }
        // MockLinks use Mavlink 2.0
        mavlink_status_t* mavlinkStatus = mavlink_get_channel_status(_mavlinkChannel);
        mavlinkStatus->flags &= ~MAVLINK_STATUS_FLAG_OUT_MAVLINK1;
130
131
132
        start();
        emit connected();
    }
133

Don Gagne's avatar
Don Gagne committed
134
135
136
    return true;
}

Don Gagne's avatar
Don Gagne committed
137
void MockLink::_disconnect(void)
Don Gagne's avatar
Don Gagne committed
138
{
139
    if (_connected) {
Don Gagne's avatar
Don Gagne committed
140
141
142
        if (_mavlinkChannel != 0) {
            qgcApp()->toolbox()->linkManager()->_freeMavlinkChannel(_mavlinkChannel);
        }
143
        _connected = false;
Daniel Agar's avatar
Daniel Agar committed
144
145
        quit();
        wait();
146
147
        emit disconnected();
    }
Don Gagne's avatar
Don Gagne committed
148
149
150
151
}

void MockLink::run(void)
{
Don Gagne's avatar
Don Gagne committed
152
153
154
    QTimer  timer1HzTasks;
    QTimer  timer10HzTasks;
    QTimer  timer500HzTasks;
155

Don Gagne's avatar
Don Gagne committed
156
157
158
    QObject::connect(&timer1HzTasks,  &QTimer::timeout, this, &MockLink::_run1HzTasks);
    QObject::connect(&timer10HzTasks, &QTimer::timeout, this, &MockLink::_run10HzTasks);
    QObject::connect(&timer500HzTasks, &QTimer::timeout, this, &MockLink::_run500HzTasks);
159

Don Gagne's avatar
Don Gagne committed
160
161
162
    timer1HzTasks.start(1000);
    timer10HzTasks.start(100);
    timer500HzTasks.start(2);
163

Don Gagne's avatar
Don Gagne committed
164
    exec();
165

Don Gagne's avatar
Don Gagne committed
166
167
168
    QObject::disconnect(&timer1HzTasks,  &QTimer::timeout, this, &MockLink::_run1HzTasks);
    QObject::disconnect(&timer10HzTasks, &QTimer::timeout, this, &MockLink::_run10HzTasks);
    QObject::disconnect(&timer500HzTasks, &QTimer::timeout, this, &MockLink::_run500HzTasks);
dogmaphobic's avatar
dogmaphobic committed
169

170
    _missionItemHandler.shutdown();
Don Gagne's avatar
Don Gagne committed
171
172
173
174
}

void MockLink::_run1HzTasks(void)
{
175
    if (_mavlinkStarted && _connected) {
DonLakeFlyer's avatar
DonLakeFlyer committed
176
177
        if (_highLatency) {
            _sendHighLatency2();
178
        } else {
DonLakeFlyer's avatar
DonLakeFlyer committed
179
            _sendVibration();
Gus Grubba's avatar
Gus Grubba committed
180
            _sendSysStatus();
DonLakeFlyer's avatar
DonLakeFlyer committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
            _sendADSBVehicles();
            if (!qgcApp()->runningUnitTests()) {
                // Sending RC Channels during unit test breaks RC tests which does it's own RC simulation
                _sendRCChannels();
            }
            if (_sendHomePositionDelayCount > 0) {
                // We delay home position for better testing
                _sendHomePositionDelayCount--;
            } else {
                _sendHomePosition();
            }
            if (_sendStatusText) {
                _sendStatusText = false;
                _sendStatusTextMessages();
            }
196
        }
Don Gagne's avatar
Don Gagne committed
197
198
199
200
201
    }
}

void MockLink::_run10HzTasks(void)
{
DonLakeFlyer's avatar
DonLakeFlyer committed
202
203
204
205
    if (_highLatency) {
        return;
    }

206
    if (_mavlinkStarted && _connected) {
Don Gagne's avatar
Don Gagne committed
207
        _sendHeartBeat();
Don Gagne's avatar
Don Gagne committed
208
209
210
211
212
213
        if (_sendGPSPositionDelayCount > 0) {
            // We delay gps position for better testing
            _sendGPSPositionDelayCount--;
        } else {
            _sendGpsRawInt();
        }
Don Gagne's avatar
Don Gagne committed
214
215
216
    }
}

Don Gagne's avatar
Don Gagne committed
217
void MockLink::_run500HzTasks(void)
Don Gagne's avatar
Don Gagne committed
218
{
DonLakeFlyer's avatar
DonLakeFlyer committed
219
220
221
222
    if (_highLatency) {
        return;
    }

223
    if (_mavlinkStarted && _connected) {
Don Gagne's avatar
Don Gagne committed
224
        _paramRequestListWorker();
225
        _logDownloadWorker();
Don Gagne's avatar
Don Gagne committed
226
227
228
229
230
    }
}

void MockLink::_loadParams(void)
{
231
232
233
234
    QFile paramFile;

    if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
        if (_vehicleType == MAV_TYPE_FIXED_WING) {
DonLakeFlyer's avatar
   
DonLakeFlyer committed
235
            paramFile.setFileName(":/FirmwarePlugin/APM/Plane.OfflineEditing.params");
Rustom Jehangir's avatar
Rustom Jehangir committed
236
        } else if (_vehicleType == MAV_TYPE_SUBMARINE ) {
237
            paramFile.setFileName(":/MockLink/APMArduSubMockLink.params");
DonLakeFlyer's avatar
   
DonLakeFlyer committed
238
239
        } else if (_vehicleType == MAV_TYPE_GROUND_ROVER ) {
            paramFile.setFileName(":/FirmwarePlugin/APM/Rover.OfflineEditing.params");
240
        } else {
DonLakeFlyer's avatar
   
DonLakeFlyer committed
241
            paramFile.setFileName(":/FirmwarePlugin/APM/Copter.OfflineEditing.params");
242
243
        }
    } else {
244
        paramFile.setFileName(":/MockLink/PX4MockLink.params");
245
246
    }

247

Don Gagne's avatar
Don Gagne committed
248
249
250
    bool success = paramFile.open(QFile::ReadOnly);
    Q_UNUSED(success);
    Q_ASSERT(success);
251

Don Gagne's avatar
Don Gagne committed
252
    QTextStream paramStream(&paramFile);
253

Don Gagne's avatar
Don Gagne committed
254
255
    while (!paramStream.atEnd()) {
        QString line = paramStream.readLine();
256

Don Gagne's avatar
Don Gagne committed
257
258
259
        if (line.startsWith("#")) {
            continue;
        }
260

Don Gagne's avatar
Don Gagne committed
261
262
        QStringList paramData = line.split("\t");
        Q_ASSERT(paramData.count() == 5);
263

Don Gagne's avatar
   
Don Gagne committed
264
        int compId = paramData.at(1).toInt();
Don Gagne's avatar
Don Gagne committed
265
266
267
        QString paramName = paramData.at(2);
        QString valStr = paramData.at(3);
        uint paramType = paramData.at(4).toUInt();
268

Don Gagne's avatar
Don Gagne committed
269
270
        QVariant paramValue;
        switch (paramType) {
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
        case MAV_PARAM_TYPE_REAL32:
            paramValue = QVariant(valStr.toFloat());
            break;
        case MAV_PARAM_TYPE_UINT32:
            paramValue = QVariant(valStr.toUInt());
            break;
        case MAV_PARAM_TYPE_INT32:
            paramValue = QVariant(valStr.toInt());
            break;
        case MAV_PARAM_TYPE_UINT16:
            paramValue = QVariant((quint16)valStr.toUInt());
            break;
        case MAV_PARAM_TYPE_INT16:
            paramValue = QVariant((qint16)valStr.toInt());
            break;
        case MAV_PARAM_TYPE_UINT8:
            paramValue = QVariant((quint8)valStr.toUInt());
            break;
        case MAV_PARAM_TYPE_INT8:
            paramValue = QVariant((qint8)valStr.toUInt());
            break;
        default:
            qCritical() << "Unknown type" << paramType;
            paramValue = QVariant(valStr.toInt());
            break;
Don Gagne's avatar
Don Gagne committed
296
        }
297

Don Gagne's avatar
Don Gagne committed
298
        qCDebug(MockLinkVerboseLog) << "Loading param" << paramName << paramValue;
299

Don Gagne's avatar
   
Don Gagne committed
300
301
        _mapParamName2Value[compId][paramName] = paramValue;
        _mapParamName2MavParamType[compId][paramName] = static_cast<MAV_PARAM_TYPE>(paramType);
Don Gagne's avatar
Don Gagne committed
302
303
304
305
306
307
308
    }
}

void MockLink::_sendHeartBeat(void)
{
    mavlink_message_t   msg;

Don Gagne's avatar
Don Gagne committed
309
310
    mavlink_msg_heartbeat_pack_chan(_vehicleSystemId,
                                    _vehicleComponentId,
Don Gagne's avatar
Don Gagne committed
311
                                    _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
312
313
314
315
316
317
                                    &msg,
                                    _vehicleType,        // MAV_TYPE
                                    _firmwareType,      // MAV_AUTOPILOT
                                    _mavBaseMode,        // MAV_MODE
                                    _mavCustomMode,      // custom mode
                                    _mavState);          // MAV_STATE
dogmaphobic's avatar
dogmaphobic committed
318

Don Gagne's avatar
Don Gagne committed
319
320
    respondWithMavlinkMessage(msg);
}
Don Gagne's avatar
Don Gagne committed
321

DonLakeFlyer's avatar
DonLakeFlyer committed
322
323
324
325
void MockLink::_sendHighLatency2(void)
{
    mavlink_message_t   msg;

326
327
328
329
    union px4_custom_mode   px4_cm;
    px4_cm.data = _mavCustomMode;

    qDebug() << "Sending" << _mavCustomMode;
DonLakeFlyer's avatar
DonLakeFlyer committed
330
331
332
333
334
335
336
    mavlink_msg_high_latency2_pack_chan(_vehicleSystemId,
                                        _vehicleComponentId,
                                        _mavlinkChannel,
                                        &msg,
                                        0,                          // timestamp
                                        _vehicleType,               // MAV_TYPE
                                        _firmwareType,              // MAV_AUTOPILOT
337
                                        px4_cm.custom_mode_hl,      // custom_mode
DonLakeFlyer's avatar
DonLakeFlyer committed
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
                                        (int32_t)(_vehicleLatitude  * 1E7),
                                        (int32_t)(_vehicleLongitude * 1E7),
                                        (int16_t)_vehicleAltitude,
                                        (int16_t)_vehicleAltitude,  // target_altitude,
                                        0,                          // heading
                                        0,                          // target_heading
                                        0,                          // target_distance
                                        0,                          // throttle
                                        0,                          // airspeed
                                        0,                          // airspeed_sp
                                        0,                          // groundspeed
                                        0,                          // windspeed,
                                        0,                          // wind_heading
                                        UINT8_MAX,                  // eph not known
                                        UINT8_MAX,                  // epv not known
                                        0,                          // temperature_air
                                        0,                          // climb_rate
                                        -1,                         // battery, do not use?
                                        0,                          // wp_num
                                        0,                          // failure_flags
                                        0, 0, 0);                   // custom0, custom1, custom2
    respondWithMavlinkMessage(msg);
}

Gus Grubba's avatar
Gus Grubba committed
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
void MockLink::_sendSysStatus(void)
{
    if(_batteryRemaining > 50) {
        _batteryRemaining = static_cast<int8_t>(100 - (_runningTime.elapsed() / 1000));
    }
    mavlink_message_t   msg;
    mavlink_msg_sys_status_pack_chan(
        _vehicleSystemId,
        _vehicleComponentId,
        static_cast<uint8_t>(_mavlinkChannel),
        &msg,
        0,          // onboard_control_sensors_present
        0,          // onboard_control_sensors_enabled
        0,          // onboard_control_sensors_health
        250,        // load
        4200 * 4,   // voltage_battery
        8000,       // current_battery
        _batteryRemaining, // battery_remaining
        0,0,0,0,0,0);
    respondWithMavlinkMessage(msg);
}

Don Gagne's avatar
Don Gagne committed
384
385
386
387
void MockLink::_sendVibration(void)
{
    mavlink_message_t   msg;

Don Gagne's avatar
Don Gagne committed
388
389
    mavlink_msg_vibration_pack_chan(_vehicleSystemId,
                                    _vehicleComponentId,
Don Gagne's avatar
Don Gagne committed
390
                                    _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
391
392
393
394
395
396
397
398
                                    &msg,
                                    0,       // time_usec
                                    50.5,    // vibration_x,
                                    10.5,    // vibration_y,
                                    60.0,    // vibration_z,
                                    1,       // clipping_0
                                    2,       // clipping_0
                                    3);      // clipping_0
Don Gagne's avatar
Don Gagne committed
399
400
401
402

    respondWithMavlinkMessage(msg);
}

Don Gagne's avatar
Don Gagne committed
403
404
405
void MockLink::respondWithMavlinkMessage(const mavlink_message_t& msg)
{
    uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
dogmaphobic's avatar
dogmaphobic committed
406

Don Gagne's avatar
Don Gagne committed
407
408
409
410
411
412
    int cBuffer = mavlink_msg_to_send_buffer(buffer, &msg);
    QByteArray bytes((char *)buffer, cBuffer);
    emit bytesReceived(this, bytes);
}

/// @brief Called when QGC wants to write bytes to the MAV
413
void MockLink::_writeBytes(const QByteArray bytes)
Don Gagne's avatar
Don Gagne committed
414
415
416
417
418
419
420
421
{
    if (_inNSH) {
        _handleIncomingNSHBytes(bytes.constData(), bytes.count());
    } else {
        if (bytes.startsWith(QByteArray("\r\r\r"))) {
            _inNSH  = true;
            _handleIncomingNSHBytes(&bytes.constData()[3], bytes.count() - 3);
        }
422

Don Gagne's avatar
Don Gagne committed
423
424
425
426
427
428
429
430
        _handleIncomingMavlinkBytes((uint8_t *)bytes.constData(), bytes.count());
    }
}

/// @brief Handle incoming bytes which are meant to be interpreted by the NuttX shell
void MockLink::_handleIncomingNSHBytes(const char* bytes, int cBytes)
{
    Q_UNUSED(cBytes);
431

Don Gagne's avatar
Don Gagne committed
432
433
434
435
436
437
438
439
    // Drop back out of NSH
    if (cBytes == 4 && bytes[0] == '\r' && bytes[1] == '\r' && bytes[2] == '\r') {
        _inNSH  = false;
        return;
    }

    if (cBytes > 0) {
        qDebug() << "NSH:" << (const char*)bytes;
440

Don Gagne's avatar
Don Gagne committed
441
442
#if 0
        // MockLink not quite ready to handle this correctly yet
Don Gagne's avatar
Don Gagne committed
443
444
445
446
        if (strncmp(bytes, "sh /etc/init.d/rc.usb\n", cBytes) == 0) {
            // This is the mavlink start command
            _mavlinkStarted = true;
        }
Don Gagne's avatar
Don Gagne committed
447
#endif
Don Gagne's avatar
Don Gagne committed
448
449
450
451
452
453
454
455
    }
}

/// @brief Handle incoming bytes which are meant to be handled by the mavlink protocol
void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes)
{
    mavlink_message_t msg;
    mavlink_status_t comm;
456

Don Gagne's avatar
Don Gagne committed
457
458
    for (qint64 i=0; i<cBytes; i++)
    {
Don Gagne's avatar
Don Gagne committed
459
        if (!mavlink_parse_char(_mavlinkChannel, bytes[i], &msg, &comm)) {
Don Gagne's avatar
Don Gagne committed
460
461
            continue;
        }
dogmaphobic's avatar
dogmaphobic committed
462

463
        if (_missionItemHandler.handleMessage(msg)) {
Don Gagne's avatar
Don Gagne committed
464
465
            continue;
        }
466

Don Gagne's avatar
Don Gagne committed
467
        switch (msg.msgid) {
468
469
470
        case MAVLINK_MSG_ID_HEARTBEAT:
            _handleHeartBeat(msg);
            break;
471

472
473
474
        case MAVLINK_MSG_ID_PARAM_REQUEST_LIST:
            _handleParamRequestList(msg);
            break;
475

476
477
478
        case MAVLINK_MSG_ID_SET_MODE:
            _handleSetMode(msg);
            break;
479

480
481
482
        case MAVLINK_MSG_ID_PARAM_SET:
            _handleParamSet(msg);
            break;
483

484
485
486
        case MAVLINK_MSG_ID_PARAM_REQUEST_READ:
            _handleParamRequestRead(msg);
            break;
dogmaphobic's avatar
dogmaphobic committed
487

488
489
490
        case MAVLINK_MSG_ID_FILE_TRANSFER_PROTOCOL:
            _handleFTP(msg);
            break;
dogmaphobic's avatar
dogmaphobic committed
491

492
493
494
        case MAVLINK_MSG_ID_COMMAND_LONG:
            _handleCommandLong(msg);
            break;
495

496
497
498
        case MAVLINK_MSG_ID_MANUAL_CONTROL:
            _handleManualControl(msg);
            break;
Don Gagne's avatar
Don Gagne committed
499

500
501
502
503
504
505
506
507
        case MAVLINK_MSG_ID_LOG_REQUEST_LIST:
            _handleLogRequestList(msg);
            break;

        case MAVLINK_MSG_ID_LOG_REQUEST_DATA:
            _handleLogRequestData(msg);
            break;

508
509
        default:
            break;
Don Gagne's avatar
Don Gagne committed
510
511
512
513
514
515
516
        }
    }
}

void MockLink::_handleHeartBeat(const mavlink_message_t& msg)
{
    Q_UNUSED(msg);
517
    qCDebug(MockLinkLog) << "Heartbeat";
Don Gagne's avatar
Don Gagne committed
518
519
520
521
522
523
}

void MockLink::_handleSetMode(const mavlink_message_t& msg)
{
    mavlink_set_mode_t request;
    mavlink_msg_set_mode_decode(&msg, &request);
524

525
    Q_ASSERT(request.target_system == _vehicleSystemId);
526

527
528
529
530
    _mavBaseMode = request.base_mode;
    _mavCustomMode = request.custom_mode;
}

Don Gagne's avatar
Don Gagne committed
531
532
533
534
535
void MockLink::_handleManualControl(const mavlink_message_t& msg)
{
    mavlink_manual_control_t manualControl;
    mavlink_msg_manual_control_decode(&msg, &manualControl);

Gus Grubba's avatar
Gus Grubba committed
536
    qCDebug(MockLinkLog) << "MANUAL_CONTROL" << manualControl.x << manualControl.y << manualControl.z << manualControl.r;
Don Gagne's avatar
Don Gagne committed
537
538
}

539
void MockLink::_setParamFloatUnionIntoMap(int componentId, const QString& paramName, float paramFloat)
540
541
{
    mavlink_param_union_t   valueUnion;
542

543
544
    Q_ASSERT(_mapParamName2Value.contains(componentId));
    Q_ASSERT(_mapParamName2Value[componentId].contains(paramName));
Don Gagne's avatar
   
Don Gagne committed
545
    Q_ASSERT(_mapParamName2MavParamType[componentId].contains(paramName));
546

547
    valueUnion.param_float = paramFloat;
548

Don Gagne's avatar
   
Don Gagne committed
549
    MAV_PARAM_TYPE paramType = _mapParamName2MavParamType[componentId][paramName];
550

551
    QVariant paramVariant;
552

553
    switch (paramType) {
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
    case MAV_PARAM_TYPE_REAL32:
        paramVariant = QVariant::fromValue(valueUnion.param_float);
        break;

    case MAV_PARAM_TYPE_UINT32:
        paramVariant = QVariant::fromValue(valueUnion.param_uint32);
        break;

    case MAV_PARAM_TYPE_INT32:
        paramVariant = QVariant::fromValue(valueUnion.param_int32);
        break;

    case MAV_PARAM_TYPE_UINT16:
        paramVariant = QVariant::fromValue(valueUnion.param_uint16);
        break;

    case MAV_PARAM_TYPE_INT16:
        paramVariant = QVariant::fromValue(valueUnion.param_int16);
        break;

    case MAV_PARAM_TYPE_UINT8:
        paramVariant = QVariant::fromValue(valueUnion.param_uint8);
        break;

    case MAV_PARAM_TYPE_INT8:
        paramVariant = QVariant::fromValue(valueUnion.param_int8);
        break;

    default:
        qCritical() << "Invalid parameter type" << paramType;
        paramVariant = QVariant::fromValue(valueUnion.param_int32);
        break;
Don Gagne's avatar
Don Gagne committed
586
    }
587

588
    qCDebug(MockLinkLog) << "_setParamFloatUnionIntoMap" << paramName << paramVariant;
589
    _mapParamName2Value[componentId][paramName] = paramVariant;
Don Gagne's avatar
Don Gagne committed
590
591
}

592
/// Convert from a parameter variant to the float value from mavlink_param_union_t
593
float MockLink::_floatUnionForParam(int componentId, const QString& paramName)
Don Gagne's avatar
Don Gagne committed
594
{
595
    mavlink_param_union_t   valueUnion;
596

597
598
    Q_ASSERT(_mapParamName2Value.contains(componentId));
    Q_ASSERT(_mapParamName2Value[componentId].contains(paramName));
Don Gagne's avatar
   
Don Gagne committed
599
    Q_ASSERT(_mapParamName2MavParamType[componentId].contains(paramName));
600

Don Gagne's avatar
   
Don Gagne committed
601
    MAV_PARAM_TYPE paramType = _mapParamName2MavParamType[componentId][paramName];
602
    QVariant paramVar = _mapParamName2Value[componentId][paramName];
603

604
    switch (paramType) {
605
    case MAV_PARAM_TYPE_REAL32:
606
        valueUnion.param_float = paramVar.toFloat();
607
        break;
608

609
610
611
612
613
614
615
    case MAV_PARAM_TYPE_UINT32:
        if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
            valueUnion.param_float = paramVar.toUInt();
        } else {
            valueUnion.param_uint32 = paramVar.toUInt();
        }
        break;
616

617
618
619
620
621
622
623
    case MAV_PARAM_TYPE_INT32:
        if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
            valueUnion.param_float = paramVar.toInt();
        } else {
            valueUnion.param_int32 = paramVar.toInt();
        }
        break;
624

625
626
627
628
629
630
631
    case MAV_PARAM_TYPE_UINT16:
        if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
            valueUnion.param_float = paramVar.toUInt();
        } else {
            valueUnion.param_uint16 = paramVar.toUInt();
        }
        break;
632

633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
    case MAV_PARAM_TYPE_INT16:
        if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
            valueUnion.param_float = paramVar.toInt();
        } else {
            valueUnion.param_int16 = paramVar.toInt();
        }
        break;

    case MAV_PARAM_TYPE_UINT8:
        if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
            valueUnion.param_float = paramVar.toUInt();
        } else {
            valueUnion.param_uint8 = paramVar.toUInt();
        }
        break;

    case MAV_PARAM_TYPE_INT8:
        if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
            valueUnion.param_float = (unsigned char)paramVar.toChar().toLatin1();
        } else {
            valueUnion.param_int8 = (unsigned char)paramVar.toChar().toLatin1();
        }
        break;

    default:
        if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
            valueUnion.param_float = paramVar.toInt();
        } else {
            valueUnion.param_int32 = paramVar.toInt();
        }
        qCritical() << "Invalid parameter type" << paramType;
664
    }
665

666
    return valueUnion.param_float;
Don Gagne's avatar
Don Gagne committed
667
668
669
670
}

void MockLink::_handleParamRequestList(const mavlink_message_t& msg)
{
Don Gagne's avatar
Don Gagne committed
671
672
673
674
    if (_failureMode == MockConfiguration::FailParamNoReponseToRequestList) {
        return;
    }

Don Gagne's avatar
Don Gagne committed
675
    mavlink_param_request_list_t request;
676

Don Gagne's avatar
Don Gagne committed
677
    mavlink_msg_param_request_list_decode(&msg, &request);
678

679
    Q_ASSERT(request.target_system == _vehicleSystemId);
680
    Q_ASSERT(request.target_component == MAV_COMP_ID_ALL);
dogmaphobic's avatar
dogmaphobic committed
681

Don Gagne's avatar
Don Gagne committed
682
683
684
685
    // Start the worker routine
    _currentParamRequestListComponentIndex = 0;
    _currentParamRequestListParamIndex = 0;
}
686

Don Gagne's avatar
Don Gagne committed
687
688
689
690
691
692
693
/// Sends the next parameter to the vehicle
void MockLink::_paramRequestListWorker(void)
{
    if (_currentParamRequestListComponentIndex == -1) {
        // Initial request complete
        return;
    }
dogmaphobic's avatar
dogmaphobic committed
694

Don Gagne's avatar
Don Gagne committed
695
696
697
    int componentId = _mapParamName2Value.keys()[_currentParamRequestListComponentIndex];
    int cParameters = _mapParamName2Value[componentId].count();
    QString paramName = _mapParamName2Value[componentId].keys()[_currentParamRequestListParamIndex];
698

Don Gagne's avatar
Don Gagne committed
699
700
701
    if ((_failureMode == MockConfiguration::FailMissingParamOnInitialReqest || _failureMode == MockConfiguration::FailMissingParamOnAllRequests) && paramName == _failParam) {
        qCDebug(MockLinkLog) << "Skipping param send:" << paramName;
    } else {
702

Don Gagne's avatar
Don Gagne committed
703
704
        char paramId[MAVLINK_MSG_ID_PARAM_VALUE_LEN];
        mavlink_message_t responseMsg;
705

Don Gagne's avatar
Don Gagne committed
706
        Q_ASSERT(_mapParamName2Value[componentId].contains(paramName));
Don Gagne's avatar
   
Don Gagne committed
707
        Q_ASSERT(_mapParamName2MavParamType[componentId].contains(paramName));
708

Don Gagne's avatar
   
Don Gagne committed
709
        MAV_PARAM_TYPE paramType = _mapParamName2MavParamType[componentId][paramName];
710

Don Gagne's avatar
Don Gagne committed
711
712
        Q_ASSERT(paramName.length() <= MAVLINK_MSG_ID_PARAM_VALUE_LEN);
        strncpy(paramId, paramName.toLocal8Bit().constData(), MAVLINK_MSG_ID_PARAM_VALUE_LEN);
dogmaphobic's avatar
dogmaphobic committed
713

Don Gagne's avatar
Don Gagne committed
714
715
        qCDebug(MockLinkLog) << "Sending msg_param_value" << componentId << paramId << paramType << _mapParamName2Value[componentId][paramId];

Don Gagne's avatar
Don Gagne committed
716
717
        mavlink_msg_param_value_pack_chan(_vehicleSystemId,
                                          componentId,                                   // component id
Don Gagne's avatar
Don Gagne committed
718
                                          _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
719
720
721
722
723
724
                                          &responseMsg,                                  // Outgoing message
                                          paramId,                                       // Parameter name
                                          _floatUnionForParam(componentId, paramName),   // Parameter value
                                          paramType,                                     // MAV_PARAM_TYPE
                                          cParameters,                                   // Total number of parameters
                                          _currentParamRequestListParamIndex);           // Index of this parameter
Don Gagne's avatar
Don Gagne committed
725
        respondWithMavlinkMessage(responseMsg);
726
    }
dogmaphobic's avatar
dogmaphobic committed
727

Don Gagne's avatar
Don Gagne committed
728
729
730
731
732
733
734
735
    // Move to next param index
    if (++_currentParamRequestListParamIndex >= cParameters) {
        // We've sent the last parameter for this component, move to next component
        if (++_currentParamRequestListComponentIndex >= _mapParamName2Value.keys().count()) {
            // We've finished sending the last parameter for the last component, request is complete
            _currentParamRequestListComponentIndex = -1;
        } else {
            _currentParamRequestListParamIndex = 0;
736
        }
Don Gagne's avatar
Don Gagne committed
737
738
739
740
741
742
743
    }
}

void MockLink::_handleParamSet(const mavlink_message_t& msg)
{
    mavlink_param_set_t request;
    mavlink_msg_param_set_decode(&msg, &request);
744

745
    Q_ASSERT(request.target_system == _vehicleSystemId);
746
    int componentId = request.target_component;
dogmaphobic's avatar
dogmaphobic committed
747

748
749
    // Param may not be null terminated if exactly fits
    char paramId[MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN + 1];
Don Gagne's avatar
Don Gagne committed
750
    paramId[MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN] = 0;
751
    strncpy(paramId, request.param_id, MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN);
752

Don Gagne's avatar
Don Gagne committed
753
    qCDebug(MockLinkLog) << "_handleParamSet" << componentId << paramId << request.param_type;
dogmaphobic's avatar
dogmaphobic committed
754

755
    Q_ASSERT(_mapParamName2Value.contains(componentId));
Don Gagne's avatar
   
Don Gagne committed
756
    Q_ASSERT(_mapParamName2MavParamType.contains(componentId));
757
    Q_ASSERT(_mapParamName2Value[componentId].contains(paramId));
Don Gagne's avatar
   
Don Gagne committed
758
    Q_ASSERT(request.param_type == _mapParamName2MavParamType[componentId][paramId]);
759

760
    // Save the new value
761
    _setParamFloatUnionIntoMap(componentId, paramId, request.param_value);
762

763
764
    // Respond with a param_value to ack
    mavlink_message_t responseMsg;
Don Gagne's avatar
Don Gagne committed
765
766
    mavlink_msg_param_value_pack_chan(_vehicleSystemId,
                                      componentId,                                               // component id
Don Gagne's avatar
Don Gagne committed
767
                                      _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
768
769
770
771
772
773
                                      &responseMsg,                                              // Outgoing message
                                      paramId,                                                   // Parameter name
                                      request.param_value,                                       // Send same value back
                                      request.param_type,                                        // Send same type back
                                      _mapParamName2Value[componentId].count(),                  // Total number of parameters
                                      _mapParamName2Value[componentId].keys().indexOf(paramId)); // Index of this parameter
Don Gagne's avatar
Don Gagne committed
774
    respondWithMavlinkMessage(responseMsg);
Don Gagne's avatar
Don Gagne committed
775
776
777
778
}

void MockLink::_handleParamRequestRead(const mavlink_message_t& msg)
{
779
    mavlink_message_t   responseMsg;
Don Gagne's avatar
Don Gagne committed
780
781
    mavlink_param_request_read_t request;
    mavlink_msg_param_request_read_decode(&msg, &request);
782

DonLakeFlyer's avatar
   
DonLakeFlyer committed
783
    const QString paramName(QString::fromLocal8Bit(request.param_id, static_cast<int>(strnlen(request.param_id, MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN))));
784
    int componentId = request.target_component;
785
786

    // special case for magic _HASH_CHECK value
Don Gagne's avatar
Don Gagne committed
787
    if (request.target_component == MAV_COMP_ID_ALL && paramName == "_HASH_CHECK") {
788
789
790
791
        mavlink_param_union_t   valueUnion;
        valueUnion.type = MAV_PARAM_TYPE_UINT32;
        valueUnion.param_uint32 = 0;
        // Special case of magic hash check value
Don Gagne's avatar
Don Gagne committed
792
793
        mavlink_msg_param_value_pack_chan(_vehicleSystemId,
                                          componentId,
Don Gagne's avatar
Don Gagne committed
794
                                          _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
795
796
797
798
799
800
                                          &responseMsg,
                                          request.param_id,
                                          valueUnion.param_float,
                                          MAV_PARAM_TYPE_UINT32,
                                          0,
                                          -1);
801
802
803
804
        respondWithMavlinkMessage(responseMsg);
        return;
    }

805
    Q_ASSERT(_mapParamName2Value.contains(componentId));
806

Don Gagne's avatar
Don Gagne committed
807
808
    char paramId[MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN + 1];
    paramId[0] = 0;
809

810
    Q_ASSERT(request.target_system == _vehicleSystemId);
811

812
813
814
    if (request.param_index == -1) {
        // Request is by param name. Param may not be null terminated if exactly fits
        strncpy(paramId, request.param_id, MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN);
Don Gagne's avatar
Don Gagne committed
815
    } else {
816
        // Request is by index
817

Don Gagne's avatar
Don Gagne committed
818
        Q_ASSERT(request.param_index >= 0 && request.param_index < _mapParamName2Value[componentId].count());
819

820
        QString key = _mapParamName2Value[componentId].keys().at(request.param_index);
821
822
        Q_ASSERT(key.length() <= MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN);
        strcpy(paramId, key.toLocal8Bit().constData());
Don Gagne's avatar
Don Gagne committed
823
    }
824

825
    Q_ASSERT(_mapParamName2Value[componentId].contains(paramId));
Don Gagne's avatar
   
Don Gagne committed
826
    Q_ASSERT(_mapParamName2MavParamType[componentId].contains(paramId));
827

Don Gagne's avatar
Don Gagne committed
828
829
830
831
832
833
    if (_failureMode == MockConfiguration::FailMissingParamOnAllRequests && strcmp(paramId, _failParam) == 0) {
        qCDebug(MockLinkLog) << "Ignoring request read for " << _failParam;
        // Fail to send this param no matter what
        return;
    }

Don Gagne's avatar
Don Gagne committed
834
835
    mavlink_msg_param_value_pack_chan(_vehicleSystemId,
                                      componentId,                                               // component id
Don Gagne's avatar
Don Gagne committed
836
                                      _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
837
838
839
                                      &responseMsg,                                              // Outgoing message
                                      paramId,                                                   // Parameter name
                                      _floatUnionForParam(componentId, paramId),                 // Parameter value
Don Gagne's avatar
   
Don Gagne committed
840
                                      _mapParamName2MavParamType[componentId][paramId],          // Parameter type
Don Gagne's avatar
Don Gagne committed
841
842
                                      _mapParamName2Value[componentId].count(),                  // Total number of parameters
                                      _mapParamName2Value[componentId].keys().indexOf(paramId)); // Index of this parameter
Don Gagne's avatar
Don Gagne committed
843
    respondWithMavlinkMessage(responseMsg);
Don Gagne's avatar
Don Gagne committed
844
845
}

Don Gagne's avatar
Don Gagne committed
846
847
848
void MockLink::emitRemoteControlChannelRawChanged(int channel, uint16_t raw)
{
    uint16_t chanRaw[18];
dogmaphobic's avatar
dogmaphobic committed
849

Don Gagne's avatar
Don Gagne committed
850
851
852
853
    for (int i=0; i<18; i++) {
        chanRaw[i] = UINT16_MAX;
    }
    chanRaw[channel] = raw;
dogmaphobic's avatar
dogmaphobic committed
854

Don Gagne's avatar
Don Gagne committed
855
    mavlink_message_t responseMsg;
Don Gagne's avatar
Don Gagne committed
856
857
    mavlink_msg_rc_channels_pack_chan(_vehicleSystemId,
                                      _vehicleComponentId,
Don Gagne's avatar
Don Gagne committed
858
                                      _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
859
860
861
862
                                      &responseMsg,          // Outgoing message
                                      0,                     // time since boot, ignored
                                      18,                    // channel count
                                      chanRaw[0],            // channel raw value
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
            chanRaw[1],            // channel raw value
            chanRaw[2],            // channel raw value
            chanRaw[3],            // channel raw value
            chanRaw[4],            // channel raw value
            chanRaw[5],            // channel raw value
            chanRaw[6],            // channel raw value
            chanRaw[7],            // channel raw value
            chanRaw[8],            // channel raw value
            chanRaw[9],            // channel raw value
            chanRaw[10],           // channel raw value
            chanRaw[11],           // channel raw value
            chanRaw[12],           // channel raw value
            chanRaw[13],           // channel raw value
            chanRaw[14],           // channel raw value
            chanRaw[15],           // channel raw value
            chanRaw[16],           // channel raw value
            chanRaw[17],           // channel raw value
            0);                    // rss
Don Gagne's avatar
Don Gagne committed
881
882
883
884
885
886
887
    respondWithMavlinkMessage(responseMsg);
}

void MockLink::_handleFTP(const mavlink_message_t& msg)
{
    Q_ASSERT(_fileServer);
    _fileServer->handleFTPMessage(msg);
Don Gagne's avatar
Don Gagne committed
888
}
889
890
891

void MockLink::_handleCommandLong(const mavlink_message_t& msg)
{
Don Gagne's avatar
Don Gagne committed
892
893
894
    static bool firstCmdUser3 = true;
    static bool firstCmdUser4 = true;

895
    mavlink_command_long_t request;
896
    uint8_t commandResult = MAV_RESULT_UNSUPPORTED;
dogmaphobic's avatar
dogmaphobic committed
897

898
899
    mavlink_msg_command_long_decode(&msg, &request);

900
901
    switch (request.command) {
    case MAV_CMD_COMPONENT_ARM_DISARM:
902
903
904
905
906
        if (request.param1 == 0.0f) {
            _mavBaseMode &= ~MAV_MODE_FLAG_SAFETY_ARMED;
        } else {
            _mavBaseMode |= MAV_MODE_FLAG_SAFETY_ARMED;
        }
907
        commandResult = MAV_RESULT_ACCEPTED;
908
909
        break;
    case MAV_CMD_PREFLIGHT_CALIBRATION:
910
911
912
        _handlePreFlightCalibration(request);
        commandResult = MAV_RESULT_ACCEPTED;
        break;
913
914
915
    case MAV_CMD_PREFLIGHT_STORAGE:
        commandResult = MAV_RESULT_ACCEPTED;
        break;
916
917
918
919
    case MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES:
        commandResult = MAV_RESULT_ACCEPTED;
        _respondWithAutopilotVersion();
        break;
Don Gagne's avatar
Don Gagne committed
920
921
922
923
924
925
926
927
928
929
930
    case MAV_CMD_USER_1:
        // Test command which always returns MAV_RESULT_ACCEPTED
        commandResult = MAV_RESULT_ACCEPTED;
        break;
    case MAV_CMD_USER_2:
        // Test command which always returns MAV_RESULT_FAILED
        commandResult = MAV_RESULT_FAILED;
        break;
    case MAV_CMD_USER_3:
        // Test command which returns MAV_RESULT_ACCEPTED on second attempt
        if (firstCmdUser3) {
DonLakeFlyer's avatar
DonLakeFlyer committed
931
932
            firstCmdUser3 = false;
            return;
Don Gagne's avatar
Don Gagne committed
933
934
935
936
937
938
939
940
        } else {
            firstCmdUser3 = true;
            commandResult = MAV_RESULT_ACCEPTED;
        }
        break;
    case MAV_CMD_USER_4:
        // Test command which returns MAV_RESULT_FAILED on second attempt
        if (firstCmdUser4) {
DonLakeFlyer's avatar
DonLakeFlyer committed
941
942
            firstCmdUser4 = false;
            return;
Don Gagne's avatar
Don Gagne committed
943
944
945
946
947
948
949
950
951
        } else {
            firstCmdUser4 = true;
            commandResult = MAV_RESULT_FAILED;
        }
        break;
    case MAV_CMD_USER_5:
        // No response
        return;
        break;
952
    }
953
954

    mavlink_message_t commandAck;
Don Gagne's avatar
Don Gagne committed
955
956
    mavlink_msg_command_ack_pack_chan(_vehicleSystemId,
                                      _vehicleComponentId,
Don Gagne's avatar
Don Gagne committed
957
                                      _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
958
959
                                      &commandAck,
                                      request.command,
DonLakeFlyer's avatar
DonLakeFlyer committed
960
                                      commandResult,
Gus Grubba's avatar
Gus Grubba committed
961
962
963
964
                                      0,    // progress
                                      0,    // result_param2
                                      0,    // target_system
                                      0);   // target_component
965
    respondWithMavlinkMessage(commandAck);
966
967
}

968
969
970
971
void MockLink::_respondWithAutopilotVersion(void)
{
    mavlink_message_t msg;

Don Gagne's avatar
Don Gagne committed
972
973
    uint8_t customVersion[8] = { };
    uint32_t flightVersion = 0;
974
#if !defined(NO_ARDUPILOT_DIALECT)
Don Gagne's avatar
Don Gagne committed
975
    if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
DonLakeFlyer's avatar
   
DonLakeFlyer committed
976
977
978
979
980
981
982
983
984
985
986
        if (_vehicleType == MAV_TYPE_FIXED_WING) {
            flightVersion |= 9 << (8*2);
        } else if (_vehicleType == MAV_TYPE_SUBMARINE ) {
            flightVersion |= 5 << (8*2);
        } else if (_vehicleType == MAV_TYPE_GROUND_ROVER ) {
            flightVersion |= 5 << (8*2);
        } else {
            flightVersion |= 6 << (8*2);
        }
        flightVersion |= 3 << (8*3);    // Major
        flightVersion |= 0 << (8*1);    // Patch
Don Gagne's avatar
Don Gagne committed
987
988
        flightVersion |= FIRMWARE_VERSION_TYPE_DEV << (8*0);
    } else if (_firmwareType == MAV_AUTOPILOT_PX4) {
989
#endif
Don Gagne's avatar
Don Gagne committed
990
991
992
993
        flightVersion |= 1 << (8*3);
        flightVersion |= 4 << (8*2);
        flightVersion |= 1 << (8*1);
        flightVersion |= FIRMWARE_VERSION_TYPE_DEV << (8*0);
994
#if !defined(NO_ARDUPILOT_DIALECT)
Don Gagne's avatar
Don Gagne committed
995
    }
996
#endif
Don Gagne's avatar
Don Gagne committed
997
998
    mavlink_msg_autopilot_version_pack_chan(_vehicleSystemId,
                                            _vehicleComponentId,
Don Gagne's avatar
Don Gagne committed
999
                                            _mavlinkChannel,
Don Gagne's avatar
Don Gagne committed
1000
                                            &msg,
For faster browsing, not all history is shown. View entire blame