Newer
Older
/****************************************************************************
*
* (c) 2009-2020 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.
*
****************************************************************************/
dogmaphobic
committed
Patrick José Pereira
committed
#include <QElapsedTimer>
#include "QGCMAVLink.h"
Q_DECLARE_LOGGING_CATEGORY(MockLinkLog)
class LinkManager;
dogmaphobic
committed
class MockConfiguration : public LinkConfiguration
{
dogmaphobic
committed
public:
MockConfiguration(const QString& name);
MockConfiguration(MockConfiguration* source);
Q_PROPERTY(int firmware READ firmware WRITE setFirmware NOTIFY firmwareChanged)
Q_PROPERTY(int vehicle READ vehicle WRITE setVehicle NOTIFY vehicleChanged)
Q_PROPERTY(bool sendStatus READ sendStatusText WRITE setSendStatusText NOTIFY sendStatusChanged)
Q_PROPERTY(bool incrementVehicleId READ incrementVehicleId WRITE setIncrementVehicleId NOTIFY incrementVehicleIdChanged)
int firmware (void) { return (int)_firmwareType; }
void setFirmware (int type) { _firmwareType = (MAV_AUTOPILOT)type; emit firmwareChanged(); }
int vehicle (void) { return (int)_vehicleType; }
bool incrementVehicleId (void) { return _incrementVehicleId; }
void setVehicle (int type) { _vehicleType = (MAV_TYPE)type; emit vehicleChanged(); }
void setIncrementVehicleId (bool incrementVehicleId) { _incrementVehicleId = incrementVehicleId; emit incrementVehicleIdChanged(); }
MAV_AUTOPILOT firmwareType (void) { return _firmwareType; }
MAV_TYPE vehicleType (void) { return _vehicleType; }
bool sendStatusText (void) { return _sendStatusText; }
void setFirmwareType (MAV_AUTOPILOT firmwareType) { _firmwareType = firmwareType; emit firmwareChanged(); }
void setVehicleType (MAV_TYPE vehicleType) { _vehicleType = vehicleType; emit vehicleChanged(); }
void setSendStatusText (bool sendStatusText) { _sendStatusText = sendStatusText; emit sendStatusChanged(); }
typedef enum {
FailNone, // No failures
FailParamNoReponseToRequestList, // Do no respond to PARAM_REQUEST_LIST
FailMissingParamOnInitialReqest, // Not all params are sent on initial request, should still succeed since QGC will re-query missing params
FailMissingParamOnAllRequests, // Not all params are sent on initial request, QGC retries will fail as well
} FailureMode_t;
FailureMode_t failureMode(void) { return _failureMode; }
void setFailureMode(FailureMode_t failureMode) { _failureMode = failureMode; }
LinkType type (void) override { return LinkConfiguration::TypeMock; }
void copyFrom (LinkConfiguration* source) override;
void loadSettings (QSettings& settings, const QString& root) override;
void saveSettings (QSettings& settings, const QString& root) override;
QString settingsURL (void) override { return "MockLinkSettings.qml"; }
QString settingsTitle (void) override { return tr("Mock Link Settings"); }
void firmwareChanged (void);
void vehicleChanged (void);
void sendStatusChanged (void);
void incrementVehicleIdChanged (void);
MAV_AUTOPILOT _firmwareType = MAV_AUTOPILOT_PX4;
MAV_TYPE _vehicleType = MAV_TYPE_QUADROTOR;
bool _sendStatusText = false;
FailureMode_t _failureMode = FailNone;
bool _incrementVehicleId = true;
dogmaphobic
committed
static const char* _sendStatusTextKey;
static const char* _incrementVehicleIdKey;
dogmaphobic
committed
};
class MockLink : public LinkInterface
{
Q_OBJECT
dogmaphobic
committed
MockLink(SharedLinkConfigurationPtr& config);
dogmaphobic
committed
int vehicleId (void) { return _vehicleSystemId; }
MAV_AUTOPILOT getFirmwareType (void) { return _firmwareType; }
void setFirmwareType (MAV_AUTOPILOT autopilot) { _firmwareType = autopilot; }
void setSendStatusText (bool sendStatusText) { _sendStatusText = sendStatusText; }
void setFailureMode (MockConfiguration::FailureMode_t failureMode) { _failureMode = failureMode; }
/// APM stack has strange handling of the first item of the mission list. If it has no
/// onboard mission items, sometimes it sends back a home position in position 0 and
/// sometimes it doesn't. Don't ask. This option allows you to configure that behavior
/// for unit testing.
void setAPMMissionResponseMode(bool sendHomePositionOnEmptyList) { _apmSendHomePositionOnEmptyList = sendHomePositionOnEmptyList; }
void emitRemoteControlChannelRawChanged(int channel, uint16_t raw);
/// Sends the specified mavlink message to QGC
void respondWithMavlinkMessage(const mavlink_message_t& msg);
dogmaphobic
committed
bool isConnected(void) const override { return _connected; }
void disconnect (void) override;
dogmaphobic
committed
/// @param failureMode Type of failure to simulate
/// @param failureAckResult Error to send if one the ack error modes
void setMissionItemFailureMode(MockLinkMissionItemHandler::FailureMode_t failureMode, MAV_MISSION_RESULT failureAckResult);
/// Called to send a MISSION_ACK message while the MissionManager is in idle state
void sendUnexpectedMissionAck(MAV_MISSION_RESULT ackType) { _missionItemHandler.sendUnexpectedMissionAck(ackType); }
/// Called to send a MISSION_ITEM message while the MissionManager is in idle state
void sendUnexpectedMissionItem(void) { _missionItemHandler.sendUnexpectedMissionItem(); }
/// Called to send a MISSION_REQUEST message while the MissionManager is in idle state
void sendUnexpectedMissionRequest(void) { _missionItemHandler.sendUnexpectedMissionRequest(); }
void sendUnexpectedCommandAck(MAV_CMD command, MAV_RESULT ackResult);
/// Reset the state of the MissionItemHandler to no items, no transactions in progress.
void resetMissionItemHandler(void) { _missionItemHandler.reset(); }
dogmaphobic
committed
/// Returns the filename for the simulated log file. Only available after a download is requested.
QString logDownloadFile(void) { return _logDownloadFilename; }
Q_INVOKABLE void setCommLost (bool commLost) { _commLost = commLost; }
Q_INVOKABLE void simulateConnectionRemoved (void);
static MockLink* startPX4MockLink (bool sendStatusText, MockConfiguration::FailureMode_t failureMode = MockConfiguration::FailNone);
static MockLink* startGenericMockLink (bool sendStatusText, MockConfiguration::FailureMode_t failureMode = MockConfiguration::FailNone);
static MockLink* startNoInitialConnectMockLink (bool sendStatusText, MockConfiguration::FailureMode_t failureMode = MockConfiguration::FailNone);
static MockLink* startAPMArduCopterMockLink (bool sendStatusText, MockConfiguration::FailureMode_t failureMode = MockConfiguration::FailNone);
static MockLink* startAPMArduPlaneMockLink (bool sendStatusText, MockConfiguration::FailureMode_t failureMode = MockConfiguration::FailNone);
static MockLink* startAPMArduSubMockLink (bool sendStatusText, MockConfiguration::FailureMode_t failureMode = MockConfiguration::FailNone);
static MockLink* startAPMArduRoverMockLink (bool sendStatusText, MockConfiguration::FailureMode_t failureMode = MockConfiguration::FailNone);
Don Gagne
committed
// Special commands for testing COMMAND_LONG handlers. By default all commands except for MAV_CMD_MOCKLINK_NO_RESPONSE_NO_RETRY should retry.
static constexpr MAV_CMD MAV_CMD_MOCKLINK_ALWAYS_RESULT_ACCEPTED = MAV_CMD_USER_1;
static constexpr MAV_CMD MAV_CMD_MOCKLINK_ALWAYS_RESULT_FAILED = MAV_CMD_USER_2;
static constexpr MAV_CMD MAV_CMD_MOCKLINK_SECOND_ATTEMPT_RESULT_ACCEPTED = MAV_CMD_USER_3;
static constexpr MAV_CMD MAV_CMD_MOCKLINK_SECOND_ATTEMPT_RESULT_FAILED = MAV_CMD_USER_4;
static constexpr MAV_CMD MAV_CMD_MOCKLINK_NO_RESPONSE = MAV_CMD_USER_5;
static constexpr MAV_CMD MAV_CMD_MOCKLINK_NO_RESPONSE_NO_RETRY = static_cast<MAV_CMD>(MAV_CMD_USER_5 + 1);
void clearSendMavCommandCounts(void) { _sendMavCommandCountMap.clear(); }
int sendMavCommandCount(MAV_CMD command) { return _sendMavCommandCountMap[command]; }
// Special message ids for testing requestMessage support
typedef enum {
FailRequestMessageNone,
FailRequestMessageCommandAcceptedMsgNotSent,
FailRequestMessageCommandUnsupported,
FailRequestMessageCommandNoResponse,
FailRequestMessageCommandAcceptedSecondAttempMsgSent,
} RequestMessageFailureMode_t;
void setRequestMessageFailureMode(RequestMessageFailureMode_t failureMode) { _requestMessageFailureMode = failureMode; }
void writeBytesQueuedSignal (const QByteArray bytes);
void highLatencyTransmissionEnabledChanged (bool highLatencyTransmissionEnabled);
// LinkInterface overrides
dogmaphobic
committed
void _writeBytesQueued(const QByteArray bytes);
void _run1HzTasks(void);
void _run10HzTasks(void);
dogmaphobic
committed
// LinkInterface overrides
bool _connect(void) override;
dogmaphobic
committed
dogmaphobic
committed
void _sendHeartBeat (void);
void _sendHighLatency2 (void);
void _handleIncomingNSHBytes (const char* bytes, int cBytes);
void _handleIncomingMavlinkBytes (const uint8_t* bytes, int cBytes);
void _loadParams (void);
void _handleHeartBeat (const mavlink_message_t& msg);
void _handleSetMode (const mavlink_message_t& msg);
void _handleParamRequestList (const mavlink_message_t& msg);
void _handleParamSet (const mavlink_message_t& msg);
void _handleParamRequestRead (const mavlink_message_t& msg);
void _handleFTP (const mavlink_message_t& msg);
void _handleCommandLong (const mavlink_message_t& msg);
void _handleManualControl (const mavlink_message_t& msg);
void _handlePreFlightCalibration (const mavlink_command_long_t& request);
void _handleLogRequestList (const mavlink_message_t& msg);
void _handleLogRequestData (const mavlink_message_t& msg);
bool _handleRequestMessage (const mavlink_command_long_t& request, bool& noAck);
float _floatUnionForParam (int componentId, const QString& paramName);
void _setParamFloatUnionIntoMap (int componentId, const QString& paramName, float paramFloat);
void _sendHomePosition (void);
void _sendGpsRawInt (void);
void _sendVibration (void);
void _sendSysStatus (void);
void _sendStatusTextMessages (void);
void _sendChunkedStatusText (uint16_t chunkId, bool missingChunks);
void _respondWithAutopilotVersion (void);
void _sendRCChannels (void);
void _paramRequestListWorker (void);
void _logDownloadWorker (void);
void _sendADSBVehicles (void);
void _moveADSBVehicle (void);
void _sendVersionMetaData (void);
void _sendParameterMetaData (void);
static MockLink* _startMockLinkWorker(QString configName, MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType, bool sendStatusText, MockConfiguration::FailureMode_t failureMode);
static MockLink* _startMockLink(MockConfiguration* mockConfig);
MockLinkMissionItemHandler _missionItemHandler;
dogmaphobic
committed
QString _name;
bool _connected;
int _mavlinkChannel;
dogmaphobic
committed
uint8_t _vehicleSystemId;
Don Gagne
committed
uint8_t _vehicleComponentId = MAV_COMP_ID_AUTOPILOT1;
dogmaphobic
committed
bool _inNSH;
bool _mavlinkStarted;
dogmaphobic
committed
uint8_t _mavBaseMode;
uint32_t _mavCustomMode;
uint8_t _mavState;
dogmaphobic
committed
static const int32_t _batteryMaxTimeRemaining = 15 * 60;
int8_t _battery1PctRemaining = 100;
int32_t _battery1TimeRemaining = _batteryMaxTimeRemaining;
MAV_BATTERY_CHARGE_STATE _battery1ChargeState = MAV_BATTERY_CHARGE_STATE_OK;
int8_t _battery2PctRemaining = 100;
int32_t _battery2TimeRemaining = _batteryMaxTimeRemaining;
MAV_BATTERY_CHARGE_STATE _battery2ChargeState = MAV_BATTERY_CHARGE_STATE_OK;
MAV_AUTOPILOT _firmwareType;
MAV_TYPE _vehicleType;
double _vehicleLatitude;
double _vehicleLongitude;
double _vehicleAltitude;
bool _commLost = false;
bool _highLatencyTransmissionEnabled = true;
int _sendHomePositionDelayCount;
int _currentParamRequestListComponentIndex; // Current component index for param request list workflow, -1 for no request in progress
int _currentParamRequestListParamIndex; // Current parameter index for param request list workflow
static const uint16_t _logDownloadLogId = 0; ///< Id of siumulated log file
static const uint32_t _logDownloadFileSize = 1000; ///< Size of simulated log file
QString _logDownloadFilename; ///< Filename for log download which is in progress
uint32_t _logDownloadCurrentOffset; ///< Current offset we are sending from
uint32_t _logDownloadBytesRemaining; ///< Number of bytes still to send, 0 = send inactive
QGeoCoordinate _adsbVehicleCoordinate;
double _adsbAngle;
RequestMessageFailureMode_t _requestMessageFailureMode = FailRequestMessageNone;
Don Gagne
committed
QMap<MAV_CMD, int> _sendMavCommandCountMap;
QMap<int, QMap<QString, QVariant>> _mapParamName2Value;
QMap<int, QMap<QString, MAV_PARAM_TYPE>> _mapParamName2MavParamType;
static double _defaultVehicleLatitude;
static double _defaultVehicleLongitude;
static double _defaultVehicleAltitude;
static int _nextVehicleSystemId;
static const char* _failParam;