Skip to content
MockLink.cc 42.1 KiB
Newer Older
/****************************************************************************
 *
 *   (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.
 *
 ****************************************************************************/
Don Gagne's avatar
Don Gagne committed

#include "MockLink.h"
#include "QGCLoggingCategory.h"
#include "QGCApplication.h"
#include "UnitTest.h"
Don Gagne's avatar
Don Gagne committed

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

#include <string.h>

Daniel Agar's avatar
Daniel Agar committed
#include "px4_custom_mode.h"

QGC_LOGGING_CATEGORY(MockLinkLog, "MockLinkLog")
Don Gagne's avatar
Don Gagne committed
QGC_LOGGING_CATEGORY(MockLinkVerboseLog, "MockLinkVerboseLog")
Don Gagne's avatar
Don Gagne committed
/// @file
///     @brief Mock implementation of a Link.
///
///     @author Don Gagne <don@thegagnes.com>

Don Gagne's avatar
Don Gagne committed
float           MockLink::_vehicleLatitude =        47.633033f;
float           MockLink::_vehicleLongitude =       -122.08794f;
float           MockLink::_vehicleAltitude =        3.5f;
int             MockLink::_nextVehicleSystemId =    128;
const char*     MockLink::_failParam =              "COM_FLTMODE6";
const char* MockConfiguration::_firmwareTypeKey =   "FirmwareType";
const char* MockConfiguration::_vehicleTypeKey =    "VehicleType";
const char* MockConfiguration::_sendStatusTextKey = "SendStatusText";
Don Gagne's avatar
Don Gagne committed
const char* MockConfiguration::_failureModeKey =    "FailureMode";
MockLink::MockLink(MockConfiguration* config)
    : _missionItemHandler(this, qgcApp()->toolbox()->mavlinkProtocol())
    , _name("MockLink")
    , _connected(false)
    , _vehicleSystemId(_nextVehicleSystemId++)
    , _vehicleComponentId(200)
    , _inNSH(false)
Don Gagne's avatar
Don Gagne committed
    , _mavlinkStarted(true)
    , _mavBaseMode(MAV_MODE_FLAG_MANUAL_INPUT_ENABLED | MAV_MODE_FLAG_CUSTOM_MODE_ENABLED)
    , _mavState(MAV_STATE_STANDBY)
Don Gagne's avatar
Don Gagne committed
    , _firmwareType(MAV_AUTOPILOT_PX4)
    , _vehicleType(MAV_TYPE_QUADROTOR)
    , _fileServer(NULL)
    , _sendStatusText(false)
Don Gagne's avatar
Don Gagne committed
    , _apmSendHomePositionOnEmptyList(false)
Don Gagne's avatar
Don Gagne committed
    , _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
    , _currentParamRequestListComponentIndex(-1)
    , _currentParamRequestListParamIndex(-1)
    , _logDownloadCurrentOffset(0)
    , _logDownloadBytesRemaining(0)
Don Gagne's avatar
Don Gagne committed
    if (_config) {
Don Gagne's avatar
Don Gagne committed
        _firmwareType = config->firmwareType();
        _vehicleType = config->vehicleType();
        _sendStatusText = config->sendStatusText();
Don Gagne's avatar
Don Gagne committed
        _failureMode = config->failureMode();
Don Gagne's avatar
Don Gagne committed
        _config->setLink(this);
Don Gagne's avatar
Don Gagne committed
    union px4_custom_mode   px4_cm;

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

    _fileServer = new MockLinkFileServer(_vehicleSystemId, _vehicleComponentId, this);
    Q_CHECK_PTR(_fileServer);
Don Gagne's avatar
Don Gagne committed
    moveToThread(this);
Don Gagne's avatar
Don Gagne committed
    _loadParams();
}

MockLink::~MockLink(void)
{
    if (!_logDownloadFilename.isEmpty()) {
        QFile::remove(_logDownloadFilename);
    }
bool MockLink::_connect(void)
    if (!_connected) {
        _connected = true;
        start();
        emit connected();
    }
Don Gagne's avatar
Don Gagne committed
    return true;
}

Don Gagne's avatar
Don Gagne committed
void MockLink::_disconnect(void)
    if (_connected) {
        _connected = false;
Daniel Agar's avatar
Daniel Agar committed
        quit();
        wait();
        emit disconnected();
    }
Don Gagne's avatar
Don Gagne committed
}

void MockLink::run(void)
{
Don Gagne's avatar
Don Gagne committed
    QTimer  timer1HzTasks;
    QTimer  timer10HzTasks;
    QTimer  timer500HzTasks;
Don Gagne's avatar
Don Gagne committed
    QObject::connect(&timer1HzTasks,  &QTimer::timeout, this, &MockLink::_run1HzTasks);
    QObject::connect(&timer10HzTasks, &QTimer::timeout, this, &MockLink::_run10HzTasks);
    QObject::connect(&timer500HzTasks, &QTimer::timeout, this, &MockLink::_run500HzTasks);
Don Gagne's avatar
Don Gagne committed
    timer1HzTasks.start(1000);
    timer10HzTasks.start(100);
    timer500HzTasks.start(2);
Don Gagne's avatar
Don Gagne committed
    exec();
Don Gagne's avatar
Don Gagne committed
    QObject::disconnect(&timer1HzTasks,  &QTimer::timeout, this, &MockLink::_run1HzTasks);
    QObject::disconnect(&timer10HzTasks, &QTimer::timeout, this, &MockLink::_run10HzTasks);
    QObject::disconnect(&timer500HzTasks, &QTimer::timeout, this, &MockLink::_run500HzTasks);
    _missionItemHandler.shutdown();
Don Gagne's avatar
Don Gagne committed
}

void MockLink::_run1HzTasks(void)
{
    if (_mavlinkStarted && _connected) {
Don Gagne's avatar
Don Gagne committed
        _sendHeartBeat();
Don Gagne's avatar
Don Gagne committed
        _sendVibration();
        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();
        }
Don Gagne's avatar
Don Gagne committed
    }
}

void MockLink::_run10HzTasks(void)
{
    if (_mavlinkStarted && _connected) {
        if (_sendGPSPositionDelayCount > 0) {
            // We delay gps position for better testing
            _sendGPSPositionDelayCount--;
        } else {
            _sendGpsRawInt();
        }
Don Gagne's avatar
Don Gagne committed
void MockLink::_run500HzTasks(void)
    if (_mavlinkStarted && _connected) {
Don Gagne's avatar
Don Gagne committed
        _paramRequestListWorker();
        _logDownloadWorker();
Don Gagne's avatar
Don Gagne committed
    }
}

void MockLink::_loadParams(void)
{
    QFile paramFile;

    if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) {
        if (_vehicleType == MAV_TYPE_FIXED_WING) {
            paramFile.setFileName(":/unittest/APMArduPlaneMockLink.params");
        } else if (_vehicleType == MAV_TYPE_SUBMARINE ) {
            paramFile.setFileName(":/unittest/APMArduSubMockLink.params");
        } else {
            paramFile.setFileName(":/unittest/APMArduCopterMockLink.params");
        }
    } else {
        paramFile.setFileName(":/unittest/PX4MockLink.params");
    }

Don Gagne's avatar
Don Gagne committed
    bool success = paramFile.open(QFile::ReadOnly);
Loading
Loading full blame...