7#include <QtCore/QTextStream>
26#include <QtCore/QEasingCurve>
27#include <QtCore/QFile>
28#include <QtCore/QStandardPaths>
29#include <QtCore/QVariantAnimation>
39 , _logReplay(!vehicle->vehicleLinkManager()->primaryLink().expired() && vehicle->vehicleLinkManager()->primaryLink().lock()->isLogReplay())
40 , _disableAllRetries(_logReplay)
41 , _waitForParamValueAckMs(
QGC::runningUnitTests() ? 50 : kWaitForParamValueAckMs)
42 , _tryftp(vehicle->apmFirmware() || vehicle->px4Firmware())
44 qCDebug(ParameterManagerLog) <<
this;
46 if (_vehicle->isOfflineEditingVehicle()) {
47 _loadOfflineEditingParams();
52 qCDebug(ParameterManagerLog) <<
this <<
"In log replay mode";
55 _hashCheckTimer.setSingleShot(
true);
57 (void) connect(&_hashCheckTimer, &QTimer::timeout,
this, &ParameterManager::_hashCheckTimeout);
59 _paramRequestListTimer.setSingleShot(
true);
60 _paramRequestListTimer.setInterval(
QGC::runningUnitTests() ? kTestInitialRequestIntervalMs : kParamRequestListTimeoutMs);
61 (void) connect(&_paramRequestListTimer, &QTimer::timeout,
this, &ParameterManager::_paramRequestListTimeout);
63 _waitingParamTimeoutTimer.setSingleShot(
true);
66 (void) connect(&_waitingParamTimeoutTimer, &QTimer::timeout,
this, &ParameterManager::_waitingParamTimeout);
70 (void) QDir().mkpath(parameterCacheDir().absolutePath());
75 qCDebug(ParameterManagerLog) <<
this;
78void ParameterManager::_updateProgressBar()
80 int waitingReadParamIndexCount = 0;
82 for (
const int compId: _waitingReadParamIndexMap.keys()) {
83 waitingReadParamIndexCount += _waitingReadParamIndexMap[compId].count();
86 if (waitingReadParamIndexCount == 0) {
87 if (_readParamIndexProgressActive) {
88 _readParamIndexProgressActive =
false;
89 _setLoadProgress(0.0);
93 _readParamIndexProgressActive =
true;
94 _setLoadProgress(
static_cast<double>(_totalParamCount - waitingReadParamIndexCount) /
static_cast<double>(_totalParamCount));
101 if (message.msgid == MAVLINK_MSG_ID_PARAM_VALUE) {
102 mavlink_param_value_t param_value{};
103 mavlink_msg_param_value_decode(&message, ¶m_value);
106 char parameterNameWithNull[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN + 1] = {};
107 (void) strncpy(parameterNameWithNull, param_value.param_id, MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN);
108 const QString parameterName(parameterNameWithNull);
112 if (_tryftp && (message.compid == MAV_COMP_ID_AUTOPILOT1) && !_initialLoadComplete
113 && (parameterName != QStringLiteral(
"_HASH_CHECK"))) {
118 paramUnion.param_float = param_value.param_value;
119 paramUnion.type = param_value.param_type;
121 QVariant parameterValue;
122 if (!_mavlinkParamUnionToVariant(paramUnion, parameterValue)) {
126 _handleParamValue(message.compid, parameterName, param_value.param_count, param_value.param_index,
static_cast<MAV_PARAM_TYPE
>(param_value.param_type), parameterValue);
130void ParameterManager::_handleParamValue(
int componentId,
const QString ¶meterName,
int parameterCount,
int parameterIndex, MAV_PARAM_TYPE mavParamType,
const QVariant ¶meterValue)
133 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) <<
134 "_parameterUpdate" <<
135 "name:" << parameterName <<
136 "count:" << parameterCount <<
137 "index:" << parameterIndex <<
138 "mavType:" << mavParamType <<
139 "value:" << parameterValue <<
144 if ((parameterIndex == 65535) && (parameterName != QStringLiteral(
"_HASH_CHECK")) && _paramRequestListTimer.isActive()) {
145 qCDebug(ParameterManagerLog) <<
"Disregarding unrequested param prior to initial list response" << parameterName;
149 if (_vehicle->
px4Firmware() && (parameterName ==
"_HASH_CHECK")) {
150 _hashCheckTimer.stop();
151 if (!_initialLoadComplete && !_logReplay) {
153 _tryCacheHashLoad(_vehicle->
id(), componentId, parameterValue);
158 _paramRequestListTimer.stop();
161 if (!_initialLoadComplete && !_logReplay && _debugCacheCRC.contains(componentId) && _debugCacheCRC[componentId]) {
162 if (_debugCacheMap[componentId].contains(parameterName)) {
163 const ParamTypeVal &cacheParamTypeVal = _debugCacheMap[componentId][parameterName];
165 const void *
const cacheData = cacheParamTypeVal.second.constData();
166 const void *
const vehicleData = parameterValue.constData();
168 if (memcmp(cacheData, vehicleData, dataSize) != 0) {
169 qCDebug(ParameterManagerVerbose1Log) <<
"Cache/Vehicle values differ for name:cache:actual" << parameterName << parameterValue << cacheParamTypeVal.second;
171 _debugCacheParamSeen[componentId][parameterName] =
true;
173 qCDebug(ParameterManagerVerbose1Log) <<
"Parameter missing from cache" << parameterName;
177 _waitingParamTimeoutTimer.stop();
180 if (!_paramCountMap.contains(componentId)) {
181 _paramCountMap[componentId] = parameterCount;
182 _totalParamCount += parameterCount;
186 if (!_waitingReadParamIndexMap.contains(componentId)) {
188 for (
int waitingIndex = 0; waitingIndex < parameterCount; waitingIndex++) {
190 _waitingReadParamIndexMap[componentId][waitingIndex] = 0;
193 qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) <<
"Seeing component for first time - paramcount:" << parameterCount;
196 if (!_waitingReadParamIndexMap[componentId].contains(parameterIndex)) {
197 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) <<
"Unrequested param update" << parameterName;
201 if (_waitingReadParamIndexMap[componentId].contains(parameterIndex)) {
202 _waitingReadParamIndexMap[componentId].remove(parameterIndex);
203 (void) _indexBatchQueue.removeOne(parameterIndex);
204 _fillIndexBatchQueue(
false );
208 int waitingReadParamIndexCount = 0;
210 for (
const int waitingComponentId: _waitingReadParamIndexMap.keys()) {
211 waitingReadParamIndexCount += _waitingReadParamIndexMap[waitingComponentId].count();
213 if (waitingReadParamIndexCount) {
214 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) <<
"waitingReadParamIndexCount:" << waitingReadParamIndexCount;
217 const int readWaitingParamCount = waitingReadParamIndexCount;
218 const int totalWaitingParamCount = readWaitingParamCount;
219 if (totalWaitingParamCount) {
221 _waitingParamTimeoutTimer.start();
222 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(-1) <<
"Restarting _waitingParamTimeoutTimer: totalWaitingParamCount:" << totalWaitingParamCount;
225 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Restarting _waitingParamTimeoutTimer (still waiting for default component params)";
226 _waitingParamTimeoutTimer.start();
228 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(-1) <<
"Not restarting _waitingParamTimeoutTimer (all requests satisfied)";
231 _updateProgressBar();
233 Fact *fact =
nullptr;
234 if (_mapCompId2FactMap.contains(componentId) && _mapCompId2FactMap[componentId].contains(parameterName)) {
235 fact = _mapCompId2FactMap[componentId][parameterName];
237 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) <<
"Adding new fact" << parameterName;
243 _mapCompId2FactMap[componentId][parameterName] = fact;
257 if (_prevWaitingReadParamIndexCount != 0 && readWaitingParamCount == 0) {
259 _writeLocalParamCache(_vehicle->
id(), componentId);
263 _prevWaitingReadParamIndexCount = waitingReadParamIndexCount;
265 _checkInitialLoadComplete();
267 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) <<
"_handleParamValue complete";
270QString ParameterManager::_vehicleAndComponentString(
int componentId)
const
273 QString vehicleIdStr;
275 vehicleIdStr = QStringLiteral(
"veh: %1").arg(_vehicle->
id());
279 QString componentIdStr;
280 if (_mapCompId2FactMap.keys().count() > 1) {
281 componentIdStr = QStringLiteral(
"comp: %1").arg(componentId);
284 if (!vehicleIdStr.isEmpty() && !componentIdStr.isEmpty()) {
285 return vehicleIdStr + QStringLiteral(
" ") + componentIdStr;
286 }
else if (!vehicleIdStr.isEmpty()) {
288 }
else if (!componentIdStr.isEmpty()) {
289 return componentIdStr;
295void ParameterManager::_mavlinkParamSet(
int componentId,
const QString ¶mName,
FactMetaData::ValueType_t valueType,
const QVariant &rawValue)
297 auto paramSetEncoder = [
this, componentId, paramName, valueType, rawValue](uint8_t , uint8_t channel,
mavlink_message_t *message) ->
void {
301 if (!_fillMavlinkParamUnion(valueType, rawValue, union_value)) {
305 char paramId[MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN + 1] = {};
306 (void) strncpy(paramId, paramName.toLocal8Bit().constData(), MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN);
308 (void) mavlink_msg_param_set_pack_chan(
313 static_cast<uint8_t
>(_vehicle->
id()),
314 static_cast<uint8_t
>(componentId),
316 union_value.param_float,
317 static_cast<uint8_t
>(paramType));
320 auto checkForCorrectParamValue = [
this, componentId, paramName, rawValue](
const mavlink_message_t &message) ->
bool {
321 if (message.compid != componentId) {
325 mavlink_param_value_t param_value{};
326 mavlink_msg_param_value_decode(&message, ¶m_value);
329 char parameterNameWithNull[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN + 1] = {};
330 (void) strncpy(parameterNameWithNull, param_value.param_id, MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN);
331 const QString parameterName(parameterNameWithNull);
333 if (parameterName != paramName) {
338 QVariant receivedValue;
340 param_union.param_float = param_value.param_value;
341 param_union.type = param_value.param_type;
342 if (!_mavlinkParamUnionToVariant(param_union, receivedValue)) {
345 if (rawValue.typeId() != receivedValue.typeId()) {
346 qCWarning(ParameterManagerLog) <<
"QVariant type mismatch on PARAM_VALUE ack for" << paramName <<
": expected type" << rawValue.typeId() <<
"got type" << receivedValue.typeId();
349 if (param_value.param_type == MAV_PARAM_TYPE_REAL32) {
353 return receivedValue == rawValue;
357 auto checkForParamError = [componentId, paramName](
const mavlink_message_t &message) ->
bool {
358 if (message.compid != componentId) {
362 mavlink_param_error_t paramError{};
363 mavlink_msg_param_error_decode(&message, ¶mError);
365 char paramId[MAVLINK_MSG_PARAM_ERROR_FIELD_PARAM_ID_LEN + 1] = {};
366 (void) strncpy(paramId, paramError.param_id, MAVLINK_MSG_PARAM_ERROR_FIELD_PARAM_ID_LEN);
368 return QString(paramId) == paramName;
388 auto incPendingWriteCountState =
new FunctionState(QStringLiteral(
"ParameterManager increment pending write count"), stateMachine, [
this]() {
389 _incrementPendingWriteCount();
391 auto decPendingWriteCountState =
new FunctionState(QStringLiteral(
"ParameterManager decrement pending write count"), stateMachine, [
this]() {
392 _decrementPendingWriteCount();
394 auto retryDecPendingWriteCountState =
new FunctionState(QStringLiteral(
"ParameterManager retry decrement pending write count"), stateMachine, [
this]() {
395 _decrementPendingWriteCount();
397 auto errorDecPendingWriteCountState =
new FunctionState(QStringLiteral(
"ParameterManager error decrement pending write count"), stateMachine, [
this]() {
398 _decrementPendingWriteCount();
400 auto waitAckState =
new WaitForParamResponseState(stateMachine, _waitForParamValueAckMs, checkForCorrectParamValue, checkForParamError);
401 auto paramRefreshState =
new FunctionState(QStringLiteral(
"ParameterManager param refresh"), stateMachine, [
this, waitAckState, componentId, paramName]() {
404 if (waitAckState->lastParamError() == MAV_PARAM_ERROR_DOES_NOT_EXIST) {
405 qCDebug(ParameterManagerLog) <<
"Skipping post-write-failure refresh, param does not exist on vehicle:" << paramName << _vehicleAndComponentString(componentId);
410 auto userNotifyState =
new FunctionState(QStringLiteral(
"ParameterManager user notify"), stateMachine, [waitAckState, paramName,
this, componentId]() {
411 const QString errorDetail = waitAckState->lastParamErrorString();
412 const QString msg = errorDetail.isEmpty()
413 ? QStringLiteral(
"Parameter write failed: param: %1 %2").arg(paramName, _vehicleAndComponentString(componentId))
414 : QStringLiteral(
"Parameter write failed: param: %1 %2 - %3").arg(paramName, _vehicleAndComponentString(componentId), errorDetail);
417 auto logSuccessState =
new FunctionState(QStringLiteral(
"ParameterManager log success"), stateMachine, [
this, componentId, paramName]() {
418 qCDebug(ParameterManagerLog) <<
"Parameter write succeeded: param:" << paramName << _vehicleAndComponentString(componentId);
421 auto logFailureState =
new FunctionState(QStringLiteral(
"ParameterManager log failure"), stateMachine, [
this, componentId, paramName]() {
422 qCDebug(ParameterManagerLog) <<
"Parameter write failed: param:" << paramName << _vehicleAndComponentString(componentId);
428 stateMachine->setInitialState(sendParamSetState);
429 sendParamSetState->addThisTransition (&
QGCState::advance, incPendingWriteCountState);
444 sendParamSetState->addThisTransition(&
QGCState::error, logFailureState);
451 qCDebug(ParameterManagerLog) <<
"Starting state machine for PARAM_SET on: " << paramName << _vehicleAndComponentString(componentId);
452 stateMachine->start();
461 paramUnion.param_uint8 =
static_cast<uint8_t
>(rawValue.toUInt(&ok));
464 paramUnion.param_int8 =
static_cast<int8_t
>(rawValue.toInt(&ok));
467 paramUnion.param_uint16 =
static_cast<uint16_t
>(rawValue.toUInt(&ok));
470 paramUnion.param_int16 =
static_cast<int16_t
>(rawValue.toInt(&ok));
473 paramUnion.param_uint32 =
static_cast<uint32_t
>(rawValue.toUInt(&ok));
476 paramUnion.param_float = rawValue.toFloat(&ok);
479 paramUnion.param_int32 =
static_cast<int32_t
>(rawValue.toInt(&ok));
482 qCCritical(ParameterManagerLog) <<
"Internal Error: Unsupported fact value type" << valueType;
483 paramUnion.param_int32 =
static_cast<int32_t
>(rawValue.toInt(&ok));
488 qCCritical(ParameterManagerLog) <<
"Fact Failed to Convert to Param Type:" << valueType;
495bool ParameterManager::_mavlinkParamUnionToVariant(
const mavlink_param_union_t ¶mUnion, QVariant &outValue)
const
497 switch (paramUnion.type) {
498 case MAV_PARAM_TYPE_REAL32:
499 outValue = QVariant(paramUnion.param_float);
501 case MAV_PARAM_TYPE_UINT8:
502 outValue = QVariant(
static_cast<quint32
>(paramUnion.param_uint8));
504 case MAV_PARAM_TYPE_INT8:
505 outValue = QVariant(
static_cast<qint32
>(paramUnion.param_int8));
507 case MAV_PARAM_TYPE_UINT16:
508 outValue = QVariant(
static_cast<quint32
>(paramUnion.param_uint16));
510 case MAV_PARAM_TYPE_INT16:
511 outValue = QVariant(
static_cast<qint32
>(paramUnion.param_int16));
513 case MAV_PARAM_TYPE_UINT32:
514 outValue = QVariant(paramUnion.param_uint32);
516 case MAV_PARAM_TYPE_INT32:
517 outValue = QVariant(paramUnion.param_int32);
520 qCCritical(ParameterManagerLog) <<
"ParameterManager::_mavlinkParamUnionToVariant - unsupported MAV_PARAM_TYPE" << paramUnion.type;
525void ParameterManager::_factRawValueUpdated(
const QVariant &rawValue)
527 Fact *
const fact = qobject_cast<Fact*>(sender());
529 qCWarning(ParameterManagerLog) <<
"Internal error";
536void ParameterManager::_ftpDownloadComplete(
const QString &fileName,
const QString &errorMsg)
538 bool continueWithDefaultParameterdownload =
true;
539 bool immediateRetry =
false;
541 _ftpDownloadInProgress =
false;
545 if (errorMsg.isEmpty()) {
546 qCDebug(ParameterManagerLog) <<
"ParameterManager::_ftpDownloadComplete : Parameter file received:" << fileName;
547 if (_parseParamFile(fileName)) {
548 qCDebug(ParameterManagerLog) <<
"ParameterManager::_ftpDownloadComplete : Parsed!";
551 qCDebug(ParameterManagerLog) <<
"ParameterManager::_ftpDownloadComplete : Error in parameter file";
554 }
else if (errorMsg.contains(
"File Not Found")) {
555 qCDebug(ParameterManagerLog) <<
"ParameterManager-ftp: No Parameterfile on vehicle - Start Conventional Parameter Download";
556 if (_initialRequestRetryCount == 0) {
557 immediateRetry =
true;
559 }
else if ((_loadProgress > 0.0001) && (_loadProgress < 0.01)) {
560 qCDebug(ParameterManagerLog) <<
"ParameterManager-ftp progress too slow - Start Conventional Parameter Download";
561 }
else if (_initialRequestRetryCount == 1) {
562 qCDebug(ParameterManagerLog) <<
"ParameterManager-ftp: Too many retries - Start Conventional Parameter Download";
564 qCDebug(ParameterManagerLog) <<
"ParameterManager-ftp Retry:" << _initialRequestRetryCount;
565 continueWithDefaultParameterdownload =
false;
568 if (continueWithDefaultParameterdownload) {
570 _initialRequestRetryCount = 0;
575 if (immediateRetry) {
576 _paramRequestListTimeout();
578 _paramRequestListTimer.start();
581 _paramRequestListTimer.start();
585void ParameterManager::_ftpDownloadProgress(
float progress)
587 qCDebug(ParameterManagerVerbose1Log) <<
"ParameterManager::_ftpDownloadProgress:" << progress;
588 _setLoadProgress(
static_cast<double>(progress));
589 if (progress > 0.001) {
590 _paramRequestListTimer.stop();
594void ParameterManager::_resetHashCheck()
596 _hashCheckTimer.stop();
597 _hashCheckDone =
false;
604 _startParameterDownload(componentId);
610 _cacheOnlyHashCheck =
true;
618 if (sharedLink->linkConfiguration()->isHighLatency() || _logReplay) {
619 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Cache-only hash check: high latency or log replay link, signalling failure";
624 if (_vehicle->
px4Firmware() && !_initialLoadComplete) {
625 _hashCheckTimer.start();
626 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Cache-only hash check: requesting _HASH_CHECK";
627 _requestHashCheck(MAV_COMP_ID_AUTOPILOT1);
629 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Cache-only hash check: not available, signalling failure";
634void ParameterManager::_startParameterDownload(uint8_t componentId)
641 if (sharedLink->linkConfiguration()->isHighLatency() || _logReplay) {
643 _parametersReady =
true;
644 _missingParameters =
true;
645 _initialLoadComplete =
true;
646 _waitingForDefaultComponent =
false;
652 if (_vehicle->
px4Firmware() && !_initialLoadComplete && !_hashCheckDone) {
654 _cacheOnlyHashCheck =
false;
655 _hashCheckTimer.start();
656 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Requesting _HASH_CHECK before full parameter list";
657 const uint8_t hashCheckCompId = (componentId == MAV_COMP_ID_ALL)
658 ?
static_cast<uint8_t
>(MAV_COMP_ID_AUTOPILOT1)
660 _requestHashCheck(hashCheckCompId);
661 }
else if (_tryftp && ((componentId == MAV_COMP_ID_ALL) || (componentId == MAV_COMP_ID_AUTOPILOT1))) {
662 if (_ftpDownloadInProgress) {
664 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Parameter file download already in progress";
667 if (!_initialLoadComplete) {
668 _paramRequestListTimer.start();
672 _waitingParamTimeoutTimer.stop();
673 if (ftpManager->
download(MAV_COMP_ID_AUTOPILOT1,
674 QStringLiteral(
"@PARAM/param.pck?withdefaults=1"),
675 QStandardPaths::writableLocation(QStandardPaths::TempLocation),
676 QStringLiteral(
"param.pck"),
678 _ftpDownloadInProgress =
true;
681 qCWarning(ParameterManagerLog) <<
"ParameterManager::_startParameterDownload FTPManager::download returned failure";
685 if (!_initialLoadComplete) {
686 _paramRequestListTimer.start();
690 for (
int cid: _paramCountMap.keys()) {
692 if ((componentId != MAV_COMP_ID_ALL) && (componentId != cid)) {
695 for (
int waitingIndex = 0; waitingIndex < _paramCountMap[cid]; waitingIndex++) {
697 _waitingReadParamIndexMap[cid][waitingIndex] = 0;
704 sharedLink->mavlinkChannel(),
711 const QString what = (componentId == MAV_COMP_ID_ALL) ?
"MAV_COMP_ID_ALL" : QString::number(componentId);
712 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Request to refresh all parameters for component ID:" << what;
715int ParameterManager::_actualComponentId(
int componentId)
const
720 qCWarning(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Default component id not set";
729 componentId = _actualComponentId(componentId);
731 qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) <<
"refreshParameter - name:" << paramName <<
")";
733 _mavlinkParamRequestRead(componentId, paramName, -1,
true );
738 componentId = _actualComponentId(componentId);
739 qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) <<
"refreshParametersPrefix - name:" << namePrefix <<
")";
741 if (!_mapCompId2FactMap.contains(componentId)) {
744 for (
const QString ¶mName: _mapCompId2FactMap[componentId].keys()) {
745 if (paramName.startsWith(namePrefix)) {
753 componentId = _actualComponentId(componentId);
755 if (!_mapCompId2FactMap.contains(componentId)) {
758 const QMap<QString, Fact *> &factMap = _mapCompId2FactMap[componentId];
759 QStringList resolved;
761 for (
const QString &entry : names) {
762 if (entry.endsWith(QLatin1Char(
'*'))) {
763 const QString prefix = entry.chopped(1);
764 if (prefix.isEmpty()) {
765 qCWarning(ParameterManagerLog) <<
"bulkRefresh: ignoring bare '*' entry";
768 for (
auto it = factMap.cbegin(); it != factMap.cend(); ++it) {
769 if (it.key().startsWith(prefix) && !seen.contains(it.key())) {
770 seen.insert(it.key());
771 resolved.append(it.key());
774 }
else if (factMap.contains(entry)) {
775 if (!seen.contains(entry)) {
777 resolved.append(entry);
780 qCWarning(ParameterManagerLog) <<
"bulkRefresh: unknown param name (skipped):" << entry;
784 if (resolved.isEmpty()) {
788 qCDebug(ParameterManagerLog) <<
"bulkRefresh: resolved" << resolved.count() <<
"params";
790 this, componentId, resolved, notifyFailure,
791 [
this, componentId](
const QString &name) {
792 _mavlinkParamRequestRead(componentId, name, -1,
false );
801 componentId = _actualComponentId(componentId);
802 if (_mapCompId2FactMap.contains(componentId)) {
803 ret = _mapCompId2FactMap[componentId].contains(_remapParamNameToVersion(paramName));
811 componentId = _actualComponentId(componentId);
813 const QString mappedParamName = _remapParamNameToVersion(paramName);
814 if (!_mapCompId2FactMap.contains(componentId) || !_mapCompId2FactMap[componentId].contains(mappedParamName)) {
815 qgcApp()->reportMissingParameter(componentId, mappedParamName);
816 return &_defaultFact;
819 return _mapCompId2FactMap[componentId][mappedParamName];
826 const int compId = _actualComponentId(componentId);
827 const QMap<QString, Fact*> &factMap = _mapCompId2FactMap[compId];
828 for (
const QString ¶mName: factMap.keys()) {
835bool ParameterManager::_fillIndexBatchQueue(
bool waitingParamTimeout)
837 if (!_indexBatchQueueActive) {
841 constexpr int maxBatchSize = 10;
843 if (waitingParamTimeout) {
845 qCDebug(ParameterManagerLog) <<
"Refilling index based batch queue due to timeout";
846 _indexBatchQueue.clear();
848 qCDebug(ParameterManagerLog) <<
"Refilling index based batch queue due to received parameter";
851 for (
const int componentId: _waitingReadParamIndexMap.keys()) {
852 if (_waitingReadParamIndexMap[componentId].count()) {
853 qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) <<
"_waitingReadParamIndexMap count" << _waitingReadParamIndexMap[componentId].count();
854 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) <<
"_waitingReadParamIndexMap (index, retry count)" << _waitingReadParamIndexMap[componentId];
857 for (
const int paramIndex: _waitingReadParamIndexMap[componentId].keys()) {
858 if (_indexBatchQueue.contains(paramIndex)) {
863 if (_indexBatchQueue.count() > maxBatchSize) {
867 _waitingReadParamIndexMap[componentId][paramIndex]++;
868 if (_disableAllRetries || (_waitingReadParamIndexMap[componentId][paramIndex] > _maxInitialLoadRetrySingleParam)) {
870 _failedReadParamIndexMap[componentId] << paramIndex;
871 qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) <<
"Giving up on (paramIndex:" << paramIndex <<
"retryCount:" << _waitingReadParamIndexMap[componentId][paramIndex] <<
")";
872 (void) _waitingReadParamIndexMap[componentId].remove(paramIndex);
875 _indexBatchQueue.append(paramIndex);
876 _mavlinkParamRequestRead(componentId, QString(), paramIndex,
false );
877 qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) <<
"Read re-request for (paramIndex:" << paramIndex <<
"retryCount:" << _waitingReadParamIndexMap[componentId][paramIndex] <<
")";
882 return (!_indexBatchQueue.isEmpty());
885void ParameterManager::_waitingParamTimeout()
891 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"_waitingParamTimeout after" << _waitingParamTimeoutTimer.interval() <<
"ms";
894 _indexBatchQueueActive =
true;
897 bool paramsRequested = _fillIndexBatchQueue(
true );
898 if (!paramsRequested && !_waitingForDefaultComponent && !_mapCompId2FactMap.contains(_vehicle->
defaultComponentId())) {
901 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Restarting _waitingParamTimeoutTimer - still don't have default component params" << _vehicle->
defaultComponentId();
902 _waitingParamTimeoutTimer.start();
903 _waitingForDefaultComponent =
true;
906 _waitingForDefaultComponent =
false;
908 _checkInitialLoadComplete();
910 if (paramsRequested) {
911 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Restarting _waitingParamTimeoutTimer - re-request";
912 _waitingParamTimeoutTimer.start();
916void ParameterManager::_requestHashCheck(uint8_t componentId)
923 qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) <<
"Sending PARAM_REQUEST_READ for _HASH_CHECK";
925 char paramId[MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN + 1] = {};
926 (void) strncpy(paramId,
"_HASH_CHECK", MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN);
929 (void) mavlink_msg_param_request_read_pack_chan(
932 sharedLink->mavlinkChannel(),
934 static_cast<uint8_t
>(_vehicle->
id()),
942void ParameterManager::_mavlinkParamRequestRead(
int componentId,
const QString ¶mName,
int paramIndex,
bool notifyFailure)
944 auto paramRequestReadEncoder = [
this, componentId, paramName, paramIndex](uint8_t , uint8_t channel,
mavlink_message_t *message) ->
void {
945 char paramId[MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN + 1] = {};
946 (void) strncpy(paramId, paramName.toLocal8Bit().constData(), MAVLINK_MSG_PARAM_REQUEST_READ_FIELD_PARAM_ID_LEN);
952 static_cast<uint8_t
>(_vehicle->
id()),
953 static_cast<uint8_t
>(componentId),
955 static_cast<int16_t
>(paramIndex));
958 auto checkForCorrectParamValue = [componentId, paramName, paramIndex](
const mavlink_message_t &message) ->
bool {
959 if (message.compid != componentId) {
963 mavlink_param_value_t param_value{};
964 mavlink_msg_param_value_decode(&message, ¶m_value);
967 char parameterNameWithNull[MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN + 1] = {};
968 (void) strncpy(parameterNameWithNull, param_value.param_id, MAVLINK_MSG_PARAM_VALUE_FIELD_PARAM_ID_LEN);
969 const QString parameterName(parameterNameWithNull);
972 if (paramIndex != -1) {
974 if (param_value.param_index != paramIndex) {
979 if (parameterName != paramName) {
987 auto checkForParamError = [componentId, paramName, paramIndex](
const mavlink_message_t &message) ->
bool {
988 if (message.compid != componentId) {
992 mavlink_param_error_t paramError{};
993 mavlink_msg_param_error_decode(&message, ¶mError);
995 char paramId[MAVLINK_MSG_PARAM_ERROR_FIELD_PARAM_ID_LEN + 1] = {};
996 (void) strncpy(paramId, paramError.param_id, MAVLINK_MSG_PARAM_ERROR_FIELD_PARAM_ID_LEN);
998 if (paramIndex != -1) {
999 return paramError.param_index == paramIndex;
1001 return QString(paramId) == paramName;
1018 auto waitAckState =
new WaitForParamResponseState(stateMachine, _waitForParamValueAckMs, checkForCorrectParamValue, checkForParamError);
1019 auto userNotifyState =
new FunctionState(QStringLiteral(
"User notify"), stateMachine, [waitAckState, paramName,
this, componentId]() {
1020 const QString errorDetail = waitAckState->lastParamErrorString();
1021 const QString msg = errorDetail.isEmpty()
1022 ? QStringLiteral(
"Parameter read failed: param: %1 %2").arg(paramName, _vehicleAndComponentString(componentId))
1023 : QStringLiteral(
"Parameter read failed: param: %1 %2 - %3").arg(paramName, _vehicleAndComponentString(componentId), errorDetail);
1026 auto logSuccessState =
new FunctionState(QStringLiteral(
"Log success"), stateMachine, [
this, componentId, paramName, paramIndex]() {
1027 qCDebug(ParameterManagerLog) <<
"PARAM_REQUEST_READ succeeded: name:" << paramName <<
"index" << paramIndex << _vehicleAndComponentString(componentId);
1030 auto logFailureState =
new FunctionState(QStringLiteral(
"Log failure"), stateMachine, [
this, componentId, paramName, paramIndex]() {
1031 qCDebug(ParameterManagerLog) <<
"PARAM_REQUEST_READ failed: param:" << paramName <<
"index" << paramIndex << _vehicleAndComponentString(componentId);
1037 stateMachine->setInitialState(sendParamRequestReadState);
1049 sendParamRequestReadState->addThisTransition(&
QGCState::error, logFailureState);
1052 if (notifyFailure) {
1059 qCDebug(ParameterManagerLog) <<
"Starting state machine for PARAM_REQUEST_READ on: " << paramName << _vehicleAndComponentString(componentId);
1060 stateMachine->start();
1063void ParameterManager::_writeLocalParamCache(
int vehicleId,
int componentId)
1065 CacheMapName2ParamTypeVal cacheMap;
1067 for (
const QString ¶mName: _mapCompId2FactMap[componentId].keys()) {
1068 const Fact *
const fact = _mapCompId2FactMap[componentId][paramName];
1069 cacheMap[paramName] = ParamTypeVal(fact->
type(), fact->
rawValue());
1073 if (cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
1074 QDataStream ds(&cacheFile);
1076 qCDebug(ParameterManagerLog) <<
"Parameter cache written" << cacheFile.fileName() <<
"paramCount:" << cacheMap.count();
1078 qCWarning(ParameterManagerLog) <<
"Failed to open cache file for writing" << cacheFile.fileName();
1085 const QFileInfo settingsFile(QSettings().fileName());
1086 const QString basePath = settingsFile.dir().absolutePath();
1087 const QString appName = settingsFile.completeBaseName();
1088 return QDir(basePath + QDir::separator() + appName + QDir::separator() + QStringLiteral(
"ParamCache"));
1093 return parameterCacheDir().filePath(QStringLiteral(
"%1_%2.v2").arg(vehicleId).arg(componentId));
1096void ParameterManager::_tryCacheHashLoad(
int vehicleId,
int componentId,
const QVariant &hashValue)
1098 qCDebug(ParameterManagerLog) <<
"Attemping load from cache";
1101 CacheMapName2ParamTypeVal cacheMap;
1103 if (!cacheFile.exists()) {
1104 qCDebug(ParameterManagerLog) <<
"Parameter cache usage failed - No parameter cache file";
1105 if (!_hashCheckDone) {
1106 _hashCheckDone =
true;
1107 if (_cacheOnlyHashCheck) {
1108 qCDebug(ParameterManagerLog) <<
"Cache-only hash check: no cache file, signalling failure";
1113 _startParameterDownload(MAV_COMP_ID_ALL);
1118 (void) cacheFile.open(QIODevice::ReadOnly);
1121 QDataStream ds(&cacheFile);
1125 uint32_t crc32_value = 0;
1126 for (
const QString &name: cacheMap.keys()) {
1127 const ParamTypeVal ¶mTypeVal = cacheMap[name];
1132 qCDebug(ParameterManagerLog) <<
"Volatile parameter" << name;
1134 const void *
const vdat = paramTypeVal.second.constData();
1136 crc32_value =
QGC::crc32(
reinterpret_cast<const uint8_t *
>(qPrintable(name)), name.length(), crc32_value);
1142 if (crc32_value == hashValue.toUInt()) {
1143 _hashCheckDone =
true;
1144 _paramRequestListTimer.stop();
1145 qCDebug(ParameterManagerLog) <<
"Parameters loaded from cache" << qPrintable(QFileInfo(cacheFile).absoluteFilePath());
1147 const int count = cacheMap.count();
1149 for (
const QString &name: cacheMap.keys()) {
1150 const ParamTypeVal ¶mTypeVal = cacheMap[name];
1153 _handleParamValue(componentId, name, count, index++, mavParamType, paramTypeVal.second);
1158 mavlink_param_set_t p{};
1162 p.param_type = MAV_PARAM_TYPE_UINT32;
1163 (void) strncpy(p.param_id,
"_HASH_CHECK",
sizeof(p.param_id));
1164 union_value.param_uint32 = crc32_value;
1165 p.param_value = union_value.param_float;
1166 p.target_system =
static_cast<uint8_t
>(_vehicle->
id());
1167 p.target_component =
static_cast<uint8_t
>(componentId);
1172 sharedLink->mavlinkChannel(),
1179 QVariantAnimation *
const ani =
new QVariantAnimation(
this);
1180 ani->setEasingCurve(QEasingCurve::OutCubic);
1181 ani->setStartValue(0.0);
1182 ani->setEndValue(1.0);
1183 ani->setDuration(750);
1185 (void) connect(ani, &QVariantAnimation::valueChanged,
this, [
this](
const QVariant &value) {
1186 _setLoadProgress(value.toDouble());
1190 connect(ani, &QVariantAnimation::finished,
this, [
this] {
1191 QTimer::singleShot(500,
this, [
this] {
1192 _setLoadProgress(0);
1196 ani->start(QAbstractAnimation::DeleteWhenStopped);
1198 qCDebug(ParameterManagerLog) <<
"Parameters cache match failed" << qPrintable(QFileInfo(cacheFile).absoluteFilePath());
1199 if (ParameterManagerDebugCacheFailureLog().isDebugEnabled()) {
1200 _debugCacheCRC[componentId] =
true;
1201 _debugCacheMap[componentId] = cacheMap;
1202 for (
const QString &name: cacheMap.keys()) {
1203 _debugCacheParamSeen[componentId][name] =
false;
1207 if (!_hashCheckDone) {
1208 _hashCheckDone =
true;
1209 if (_cacheOnlyHashCheck) {
1210 qCDebug(ParameterManagerLog) <<
"Cache-only hash check: CRC mismatch, signalling failure";
1215 _startParameterDownload(MAV_COMP_ID_ALL);
1223 stream <<
"# Onboard parameters for Vehicle " << _vehicle->
id() <<
"\n";
1228 stream <<
"# Version: "
1233 stream <<
"# Git Revision: " << _vehicle->
gitHash() <<
"\n";
1236 stream <<
"# Vehicle-Id Component-Id Name Value Type\n";
1238 for (
const int componentId: _mapCompId2FactMap.keys()) {
1239 for (
const QString ¶mName: _mapCompId2FactMap[componentId].keys()) {
1240 const Fact *
const fact = _mapCompId2FactMap[componentId][paramName];
1244 qCWarning(ParameterManagerLog) <<
"Internal error: missing fact";
1256 return MAV_PARAM_TYPE_UINT8;
1258 return MAV_PARAM_TYPE_INT8;
1260 return MAV_PARAM_TYPE_UINT16;
1262 return MAV_PARAM_TYPE_INT16;
1264 return MAV_PARAM_TYPE_UINT32;
1266 return MAV_PARAM_TYPE_UINT64;
1268 return MAV_PARAM_TYPE_INT64;
1270 return MAV_PARAM_TYPE_REAL32;
1272 return MAV_PARAM_TYPE_REAL64;
1274 qCWarning(ParameterManagerLog) <<
"Unsupported fact type" << factType;
1277 return MAV_PARAM_TYPE_INT32;
1284 case MAV_PARAM_TYPE_UINT8:
1286 case MAV_PARAM_TYPE_INT8:
1288 case MAV_PARAM_TYPE_UINT16:
1290 case MAV_PARAM_TYPE_INT16:
1292 case MAV_PARAM_TYPE_UINT32:
1294 case MAV_PARAM_TYPE_UINT64:
1296 case MAV_PARAM_TYPE_INT64:
1298 case MAV_PARAM_TYPE_REAL32:
1300 case MAV_PARAM_TYPE_REAL64:
1303 qCWarning(ParameterManagerLog) <<
"Unsupported mav param type" << mavType;
1305 case MAV_PARAM_TYPE_INT32:
1310void ParameterManager::_checkInitialLoadComplete()
1312 if (_initialLoadComplete) {
1316 for (
const int componentId: _waitingReadParamIndexMap.keys()) {
1317 if (!_waitingReadParamIndexMap[componentId].isEmpty()) {
1329 _initialLoadComplete =
true;
1332 for (
const int componentId: _debugCacheParamSeen.keys()) {
1333 if (!_logReplay && _debugCacheCRC.contains(componentId) && _debugCacheCRC[componentId]) {
1334 for (
const QString ¶mName: _debugCacheParamSeen[componentId].keys()) {
1335 if (!_debugCacheParamSeen[componentId][paramName]) {
1336 qCDebug(ParameterManagerLog) <<
"Parameter in cache but not on vehicle componentId:Name" << componentId << paramName;
1341 _debugCacheCRC.clear();
1343 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Initial load complete";
1347 bool initialLoadFailures =
false;
1348 for (
const int componentId: _failedReadParamIndexMap.keys()) {
1349 for (
const int paramIndex: _failedReadParamIndexMap[componentId]) {
1350 if (initialLoadFailures) {
1353 indexList += QStringLiteral(
"%1:%2").arg(componentId).arg(paramIndex);
1354 initialLoadFailures =
true;
1355 qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) <<
"Gave up on initial load after max retries (paramIndex:" << paramIndex <<
")";
1359 _missingParameters =
false;
1360 if (initialLoadFailures) {
1361 _missingParameters =
true;
1362 const QString errorMsg = tr(
"%1 was unable to retrieve the full set of parameters from vehicle %2. "
1363 "This will cause %1 to be unable to display its full user interface. "
1364 "If you are using modified firmware, you may need to resolve any vehicle startup errors to resolve the issue. "
1365 "If you are using standard firmware, you may need to upgrade to a newer version to resolve the issue.").arg(QCoreApplication::applicationName()).arg(_vehicle->
id());
1366 qCDebug(ParameterManagerLog) << errorMsg;
1369 qCWarning(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"The following parameter indices could not be loaded after the maximum number of retries:" << indexList;
1374 _parametersReady =
true;
1380void ParameterManager::_hashCheckTimeout()
1382 _hashCheckDone =
true;
1383 if (_cacheOnlyHashCheck) {
1384 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"_HASH_CHECK timed out in cache-only mode, signalling failure";
1388 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"_HASH_CHECK timed out, falling back to parameter download";
1389 _startParameterDownload(MAV_COMP_ID_ALL);
1392void ParameterManager::_paramRequestListTimeout()
1396 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"_paramRequestListTimeout (log replay): Signalling load complete";
1397 _initialLoadComplete =
true;
1398 _missingParameters =
false;
1399 _parametersReady =
true;
1406 if (!_disableAllRetries && (++_initialRequestRetryCount <= _maxInitialRequestListRetry)) {
1407 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Retrying initial parameter request list";
1408 _startParameterDownload(MAV_COMP_ID_ALL);
1412 qCDebug(ParameterManagerLog) << _logVehiclePrefix(-1) <<
"Initial parameter request list retries exhausted, giving up";
1414 const QString errorMsg = tr(
"Vehicle %1 did not respond to request for parameters. "
1415 "This will cause %2 to be unable to display its full user interface.").arg(_vehicle->
id()).arg(QCoreApplication::applicationName());
1416 qCDebug(ParameterManagerLog) << errorMsg;
1422QString ParameterManager::_remapParamNameToVersion(
const QString ¶mName)
const
1424 static const QString noRemapPrefix = QStringLiteral(
"noremap.");
1425 if (paramName.startsWith(noRemapPrefix)) {
1426 return paramName.mid(noRemapPrefix.length());
1438 if (!majorVersionRemap.contains(majorVersion)) {
1440 qCDebug(ParameterManagerVerbose1Log) <<
"_remapParamNameToVersion: no major version mapping";
1446 QString mappedParamName = paramName;
1448 if (remapMinorVersion.contains(currentMinorVersion)) {
1450 if (remap.contains(mappedParamName)) {
1451 const QString toParamName = remap[mappedParamName];
1452 qCDebug(ParameterManagerLog) <<
"_remapParamNameToVersion: remapped currentMinor:from:to" << currentMinorVersion << mappedParamName << toParamName;
1453 mappedParamName = toParamName;
1458 return mappedParamName;
1461void ParameterManager::_loadOfflineEditingParams()
1464 if (paramFilename.isEmpty()) {
1468 QFile paramFile(paramFilename);
1469 if (!paramFile.open(QFile::ReadOnly)) {
1470 qCWarning(ParameterManagerLog) <<
"Unable to open offline editing params file" << paramFilename;
1473 QTextStream paramStream(¶mFile);
1474 while (!paramStream.atEnd()) {
1475 const QString line = paramStream.readLine();
1476 if (line.startsWith(
"#")) {
1480 const QStringList paramData = line.split(
"\t");
1481 Q_ASSERT(paramData.count() == 5);
1483 const int offlineDefaultComponentId = paramData.at(1).toInt();
1485 const QString paramName = paramData.at(2);
1486 const QString valStr = paramData.at(3);
1487 const MAV_PARAM_TYPE paramType =
static_cast<MAV_PARAM_TYPE
>(paramData.at(4).toUInt());
1489 QVariant paramValue;
1490 switch (paramType) {
1491 case MAV_PARAM_TYPE_REAL32:
1492 paramValue = QVariant(valStr.toFloat());
1494 case MAV_PARAM_TYPE_UINT32:
1495 paramValue = QVariant(valStr.toUInt());
1497 case MAV_PARAM_TYPE_UINT16:
1498 paramValue = QVariant((quint16)valStr.toUInt());
1500 case MAV_PARAM_TYPE_INT16:
1501 paramValue = QVariant((qint16)valStr.toInt());
1503 case MAV_PARAM_TYPE_UINT8:
1504 paramValue = QVariant((quint8)valStr.toUInt());
1506 case MAV_PARAM_TYPE_INT8:
1507 paramValue = QVariant((qint8)valStr.toUInt());
1510 qCCritical(ParameterManagerLog) <<
"Unknown type" << paramType;
1512 case MAV_PARAM_TYPE_INT32:
1513 paramValue = QVariant(valStr.toInt());
1525 _parametersReady =
true;
1526 _initialLoadComplete =
true;
1527 _debugCacheCRC.clear();
1533 MAV_CMD_PREFLIGHT_STORAGE,
1543 if (sysAutoConfigFact) {
1548QString ParameterManager::_logVehiclePrefix(
int componentId)
const
1550 if (componentId == -1) {
1551 return QStringLiteral(
"V:%1").arg(_vehicle->
id());
1553 return QStringLiteral(
"V:%1 C:%2").arg(_vehicle->
id()).arg(componentId);
1557void ParameterManager::_setLoadProgress(
double loadProgress)
1567 if (_parameterDownloadSkipped != skipped) {
1568 _parameterDownloadSkipped = skipped;
1575 return _paramCountMap.keys();
1580 return _pendingWritesCount > 0;
1583#ifdef QGC_UNITTEST_BUILD
1584void ParameterManager::setPendingWritesForTest(
bool pending)
1586 const bool wasPending = (_pendingWritesCount > 0);
1587 _pendingWritesCount = pending ? 1 : 0;
1588 if (wasPending != pending) {
1600bool ParameterManager::_parseParamFile(
const QString& filename)
1602 constexpr quint16 magic_standard = 0x671B;
1603 constexpr quint16 magic_withdefaults = 0x671C;
1604 quint32 no_of_parameters_found = 0;
1605 constexpr int componentId = MAV_COMP_ID_AUTOPILOT1;
1616 qCDebug(ParameterManagerLog) <<
"_parseParamFile:" << filename;
1617 QFile file(filename);
1618 if (!file.open(QIODevice::ReadOnly)) {
1619 qCDebug(ParameterManagerLog) <<
"_parseParamFile: Error: Could not open downloaded parameter file.";
1623 QDataStream in(&file);
1624 in.setByteOrder(QDataStream::LittleEndian);
1626 quint16 magic, num_params, total_params;
1631 if (in.status() != QDataStream::Ok) {
1632 qCDebug(ParameterManagerLog) <<
"_parseParamFile: Error: Could not read Header";
1636 qCDebug(ParameterManagerVerbose2Log) <<
"_parseParamFile: magic: 0x" << Qt::hex << magic;
1637 qCDebug(ParameterManagerVerbose2Log) <<
"_parseParamFile: num_params:" << num_params
1638 <<
"total_params:" << total_params;
1640 if ((magic != magic_standard) && (magic != magic_withdefaults)) {
1641 qCDebug(ParameterManagerLog) <<
"_parseParamFile: Error: File does not start with Magic";
1644 if (num_params > total_params) {
1645 qCDebug(ParameterManagerLog) <<
"_parseParamFile: Error: total_params > num_params";
1648 if (num_params != total_params) {
1650 qCDebug(ParameterManagerLog) <<
"_parseParamFile: Error: total_params != num_params";
1654 while (in.status() == QDataStream::Ok) {
1658 quint8 name_len = 0;
1659 quint8 common_len = 0;
1660 bool withdefault =
false;
1662 char name_buffer[17];
1664 while (
byte == 0x0) {
1666 if (in.status() != QDataStream::Ok) {
1667 if (no_of_parameters_found == num_params) {
1670 qCDebug(ParameterManagerLog) <<
"_parseParamFile: Error: unexpected EOF"
1671 <<
"number of parameters expected:" << num_params
1672 <<
"actual:" << no_of_parameters_found;
1677 ptype =
byte & 0x0F;
1678 flags = (
byte >> 4) & 0x0F;
1679 withdefault = (flags & 0x01) == 0x01;
1681 if (in.status() != QDataStream::Ok) {
1682 qCCritical(ParameterManagerLog) <<
"_parseParamFile: Error: Unexpected EOF while reading flags";
1685 name_len = ((
byte >> 4) & 0x0F) + 1;
1686 common_len =
byte & 0x0F;
1687 if ((name_len + common_len) > 16) {
1688 qCCritical(ParameterManagerLog) <<
"_parseParamFile: Error: common_len + name_len > 16"
1689 <<
"name_len" << name_len
1690 <<
"common_len" << common_len;
1693 no_read = in.readRawData(&name_buffer[common_len],
static_cast<int>(name_len));
1694 if (no_read != name_len) {
1695 qCCritical(ParameterManagerLog) <<
"_parseParamFile: Error: Unexpected EOF while reading parameterName"
1696 <<
"Expected:" << name_len
1697 <<
"Actual:" << no_read;
1700 name_buffer[common_len + name_len] =
'\0';
1701 const QString parameterName(name_buffer);
1702 qCDebug(ParameterManagerVerbose2Log) <<
"_parseParamFile: parameter" << parameterName
1703 <<
"name_len" << name_len
1704 <<
"common_len" << common_len
1706 <<
"flags" << flags;
1708 QVariant parameterValue = 0;
1709 QVariant defaultValue;
1710 switch (
static_cast<ap_var_type
>(ptype)) {
1717 parameterValue = data8;
1720 defaultValue = data8;
1723 case AP_PARAM_INT16:
1725 parameterValue = data16;
1728 defaultValue = data16;
1731 case AP_PARAM_INT32:
1733 parameterValue = data32;
1736 defaultValue = data32;
1739 case AP_PARAM_FLOAT:
1741 (void) memcpy(&dfloat, &data32, 4);
1742 parameterValue = dfloat;
1746 (void) memcpy(&ddefault, &data32, 4);
1747 defaultValue = ddefault;
1751 qCDebug(ParameterManagerLog) <<
"_parseParamFile: Error: type is out of range" << ptype;
1755 qCDebug(ParameterManagerVerbose2Log) <<
"paramValue" << parameterValue;
1757 if (++no_of_parameters_found > num_params) {
1758 qCDebug(ParameterManagerLog) <<
"_parseParamFile: Error: more parameters in file than expected."
1759 <<
"Expected:" << num_params
1760 <<
"Actual:" << no_of_parameters_found;
1765 (ptype == AP_PARAM_INT16) ?
FactMetaData::valueTypeInt16 :
1766 (ptype == AP_PARAM_INT32) ?
FactMetaData::valueTypeInt32 :
1769 Fact *fact =
nullptr;
1770 if (_mapCompId2FactMap.contains(componentId) && _mapCompId2FactMap[componentId].contains(parameterName)) {
1771 fact = _mapCompId2FactMap[componentId][parameterName];
1772 if (withdefault && defaultValue.isValid()) {
1779 qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) <<
"Adding new fact" << parameterName;
1781 fact =
new Fact(componentId, parameterName, factType,
this);
1785 _mapCompId2FactMap[componentId][parameterName] = fact;
1791 if (withdefault && defaultValue.isValid()) {
1803 _paramCountMap[componentId] = num_params;
1804 _totalParamCount += num_params;
1805 _waitingReadParamIndexMap[componentId] = QMap<int, int>();
1807 _writeLocalParamCache(_vehicle->
id(), componentId);
1809 _checkInitialLoadComplete();
1810 _setLoadProgress(0.0);
1818void ParameterManager::_incrementPendingWriteCount()
1820 _pendingWritesCount++;
1821 if (_pendingWritesCount == 1) {
1826void ParameterManager::_decrementPendingWriteCount()
1828 if (_pendingWritesCount == 0) {
1829 qCWarning(ParameterManagerLog) <<
"Internal Error: _pendingWriteCount == 0";
1833 _pendingWritesCount--;
1834 if (_pendingWritesCount == 0) {
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
struct param_union mavlink_param_union_t
virtual void parametersReadyPreChecks()
FactMetaData * factMetaDataForName(const QString &name, FactMetaData::ValueType_t valueType)
void commandProgress(float value)
void downloadComplete(const QString &file, const QString &errorMsg)
bool download(uint8_t fromCompId, const QString &fromURI, const QString &toDir, const QString &fileName="", bool checksize=true)
A Fact is used to hold a single value within the system.
void setMetaData(FactMetaData *metaData, bool setDefaultFromMetaData=false)
void containerSetRawValue(const QVariant &value)
Value coming from Vehicle. This does NOT send a _containerRawValueChanged signal.
FactMetaData * metaData()
FactMetaData::ValueType_t type() const
void setRawValue(const QVariant &value)
void containerRawValueChanged(const QVariant &value)
This signal is meant for use by Fact container implementations. Used to send changed values to vehicl...
QString rawValueStringFullPrecision() const
Returns the values as a string with full 18 digit precision if float/double.
QVariant rawValue() const
QMap< int, remapParamNameMap_t > remapParamNameMinorVersionRemapMap_t
virtual int remapParamNameHigestMinorVersionNumber(int) const
QMap< QString, QString > remapParamNameMap_t
virtual QString offlineEditingParamFile(Vehicle *) const
Return the resource file which contains the set of params loaded for offline editing.
QMap< int, remapParamNameMinorVersionRemapMap_t > remapParamNameMajorVersionMap_t
virtual const remapParamNameMajorVersionMap_t & paramNameRemapMajorVersionMap() const
static int getComponentId()
static MAVLinkProtocol * instance()
static MultiVehicleManager * instance()
bool parameterExists(int componentId, const QString ¶mName) const
void parameterDownloadSkippedChanged()
void mavlinkMessageReceived(const mavlink_message_t &message)
Fact * getParameter(int componentId, const QString ¶mName)
void factAdded(int componentId, Fact *fact)
static FactMetaData::ValueType_t mavTypeToFactType(MAV_PARAM_TYPE mavType)
void setParameterDownloadSkipped(bool skipped)
QList< int > componentIds() const
void refreshParametersPrefix(int componentId, const QString &namePrefix)
Request a refresh on all parameters that begin with the specified prefix.
void initialParametersRequestFailed()
Vehicle never responded to PARAM_REQUEST_LIST, all retries exhausted.
void parametersReadyChanged(bool parametersReady)
double loadProgress() const
void bulkRefresh(int componentId, const QStringList &names, bool notifyFailure=true)
void tryHashCheckCacheLoad()
bool pendingWrites() const
static QDir parameterCacheDir()
void missingParametersChanged(bool missingParameters)
static constexpr int defaultComponentId
void resetAllParametersToDefaults()
QStringList parameterNames(int componentId) const
Returns all parameter names.
void _paramRequestReadFailure(int componentId, const QString ¶mName, int paramIndex)
void _paramRequestReadSuccess(int componentId, const QString ¶mName, int paramIndex)
static constexpr int kParamSetRetryCount
Number of retries for PARAM_SET.
void _paramSetSuccess(int componentId, const QString ¶mName)
void loadProgressChanged(float value)
void cacheCheckOnlyFailed()
void refreshParameter(int componentId, const QString ¶mName)
Request a refresh on the specific parameter.
void pendingWritesChanged(bool pendingWrites)
static MAV_PARAM_TYPE factTypeToMavType(FactMetaData::ValueType_t factType)
static constexpr int kParamRequestReadRetryCount
Number of retries for PARAM_REQUEST_READ.
void resetAllToVehicleConfiguration()
Q_INVOKABLE void refreshAllParameters()
static QString parameterCacheFile(int vehicleId, int componentId)
void writeParametersToStream(QTextStream &stream) const
void _paramSetFailure(int componentId, const QString ¶mName)
Final state for a QGCStateMachine with logging support.
static VehicleClass_t vehicleClass(MAV_TYPE mavType)
static const char * vehicleClassToCanonicalString(VehicleClass_t vehicleClass)
static FirmwareClass_t firmwareClass(MAV_AUTOPILOT autopilot)
static const char * firmwareClassToCanonicalString(FirmwareClass_t firmwareClass)
QGroundControl specific state machine with enhanced error handling.
QSignalTransition * addThisTransition(PointerToMemberFunction signal, QAbstractState *target)
Simpler version of QState::addTransition which assumes the sender is this.
Sends the specified MAVLink message to the vehicle.
WeakLinkInterfacePtr primaryLink() const
void sendMavCommand(int compId, MAV_CMD command, bool showError, float param1=0.0f, float param2=0.0f, float param3=0.0f, float param4=0.0f, float param5=0.0f, float param6=0.0f, float param7=0.0f)
QString firmwareVersionTypeString() const
MAV_TYPE vehicleType() const
VehicleLinkManager * vehicleLinkManager()
FirmwarePlugin * firmwarePlugin()
Provides access to the Firmware Plugin for this Vehicle.
ComponentInformationManager * compInfoManager()
int firmwareMinorVersion() const
MAV_AUTOPILOT firmwareType() const
bool sendMessageOnLinkThreadSafe(LinkInterface *link, mavlink_message_t message)
int defaultComponentId() const
bool genericFirmware() const
AutoPilotPlugin * autopilotPlugin()
Provides access to AutoPilotPlugin for this vehicle.
void setOfflineEditingDefaultComponentId(int defaultComponentId)
Sets the default component id for an offline editing vehicle.
int firmwarePatchVersion() const
FTPManager * ftpManager()
int firmwareMajorVersion() const
Waits for either PARAM_VALUE (success) or PARAM_ERROR (rejection) from the vehicle.
Error
Error codes for decompression operations.
quint32 crc32(const quint8 *src, unsigned len, unsigned state)
bool fuzzyCompare(double value1, double value2)
Returns true if the two values are equal or close. Correctly handles 0 and NaN values.
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
static const int versionNotSetValue