|
|
|
@ -7,10 +7,6 @@
@@ -7,10 +7,6 @@
|
|
|
|
|
* |
|
|
|
|
****************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @file
|
|
|
|
|
/// @author Don Gagne <don@thegagnes.com>
|
|
|
|
|
|
|
|
|
|
#include "ParameterManager.h" |
|
|
|
|
#include "QGCApplication.h" |
|
|
|
|
#include "QGCLoggingCategory.h" |
|
|
|
@ -27,9 +23,8 @@
@@ -27,9 +23,8 @@
|
|
|
|
|
#include <QJsonArray> |
|
|
|
|
|
|
|
|
|
/* types for local parameter cache */ |
|
|
|
|
typedef QPair<int, QVariant> ParamTypeVal; |
|
|
|
|
typedef QPair<QString, ParamTypeVal> NamedParam; |
|
|
|
|
typedef QMap<int, NamedParam> MapID2NamedParam; |
|
|
|
|
typedef QPair<int /* FactMetaData::ValueType_t */, QVariant /* Fact::rawValue */> ParamTypeVal; |
|
|
|
|
typedef QMap<QString /* parameter name */, ParamTypeVal> CacheMapName2ParamTypeVal; |
|
|
|
|
|
|
|
|
|
QGC_LOGGING_CATEGORY(ParameterManagerVerbose1Log, "ParameterManagerVerbose1Log") |
|
|
|
|
QGC_LOGGING_CATEGORY(ParameterManagerVerbose2Log, "ParameterManagerVerbose2Log") |
|
|
|
@ -43,25 +38,26 @@ const char* ParameterManager::_jsonParamNameKey = "name";
@@ -43,25 +38,26 @@ const char* ParameterManager::_jsonParamNameKey = "name";
|
|
|
|
|
const char* ParameterManager::_jsonParamValueKey = "value"; |
|
|
|
|
|
|
|
|
|
ParameterManager::ParameterManager(Vehicle* vehicle) |
|
|
|
|
: QObject(vehicle) |
|
|
|
|
, _vehicle(vehicle) |
|
|
|
|
, _mavlink(NULL) |
|
|
|
|
, _loadProgress(0.0) |
|
|
|
|
, _parametersReady(false) |
|
|
|
|
, _missingParameters(false) |
|
|
|
|
, _initialLoadComplete(false) |
|
|
|
|
, _waitingForDefaultComponent(false) |
|
|
|
|
, _saveRequired(false) |
|
|
|
|
, _logReplay(vehicle->priorityLink() && vehicle->priorityLink()->isLogReplay()) |
|
|
|
|
, _parameterSetMajorVersion(-1) |
|
|
|
|
, _parameterMetaData(NULL) |
|
|
|
|
, _prevWaitingReadParamIndexCount(0) |
|
|
|
|
, _prevWaitingReadParamNameCount(0) |
|
|
|
|
, _prevWaitingWriteParamNameCount(0) |
|
|
|
|
, _initialRequestRetryCount(0) |
|
|
|
|
, _disableAllRetries(false) |
|
|
|
|
, _indexBatchQueueActive(false) |
|
|
|
|
, _totalParamCount(0) |
|
|
|
|
: QObject (vehicle) |
|
|
|
|
, _vehicle (vehicle) |
|
|
|
|
, _mavlink (NULL) |
|
|
|
|
, _loadProgress (0.0) |
|
|
|
|
, _parametersReady (false) |
|
|
|
|
, _missingParameters (false) |
|
|
|
|
, _initialLoadComplete (false) |
|
|
|
|
, _waitingForDefaultComponent (false) |
|
|
|
|
, _saveRequired (false) |
|
|
|
|
, _metaDataAddedToFacts (false) |
|
|
|
|
, _logReplay (vehicle->priorityLink() && vehicle->priorityLink()->isLogReplay()) |
|
|
|
|
, _parameterSetMajorVersion (-1) |
|
|
|
|
, _parameterMetaData (NULL) |
|
|
|
|
, _prevWaitingReadParamIndexCount (0) |
|
|
|
|
, _prevWaitingReadParamNameCount (0) |
|
|
|
|
, _prevWaitingWriteParamNameCount (0) |
|
|
|
|
, _initialRequestRetryCount (0) |
|
|
|
|
, _disableAllRetries (false) |
|
|
|
|
, _indexBatchQueueActive (false) |
|
|
|
|
, _totalParamCount (0) |
|
|
|
|
{ |
|
|
|
|
_versionParam = vehicle->firmwarePlugin()->getVersionParam(); |
|
|
|
|
|
|
|
|
@ -137,10 +133,12 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
@@ -137,10 +133,12 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
|
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (_vehicle->px4Firmware() && parameterName == "_HASH_CHECK" && !_logReplay) { |
|
|
|
|
/* we received a cache hash, potentially load from cache */ |
|
|
|
|
_tryCacheHashLoad(vehicleId, componentId, value); |
|
|
|
|
return; |
|
|
|
|
if (_vehicle->px4Firmware() && parameterName == "_HASH_CHECK") { |
|
|
|
|
if (!_initialLoadComplete && !_logReplay) { |
|
|
|
|
/* we received a cache hash, potentially load from cache */ |
|
|
|
|
_tryCacheHashLoad(vehicleId, componentId, value); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_initialRequestTimeoutTimer.stop(); |
|
|
|
@ -154,8 +152,6 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
@@ -154,8 +152,6 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
|
|
|
|
|
_totalParamCount += parameterCount; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_mapParameterId2Name[componentId][parameterId] = parameterName; |
|
|
|
|
|
|
|
|
|
// If we've never seen this component id before, setup the wait lists.
|
|
|
|
|
if (!_waitingReadParamIndexMap.contains(componentId)) { |
|
|
|
|
// Add all indices to the wait list, parameter index is 0-based
|
|
|
|
@ -735,19 +731,18 @@ void ParameterManager::_writeParameterRaw(int componentId, const QString& paramN
@@ -735,19 +731,18 @@ void ParameterManager::_writeParameterRaw(int componentId, const QString& paramN
|
|
|
|
|
|
|
|
|
|
void ParameterManager::_writeLocalParamCache(int vehicleId, int componentId) |
|
|
|
|
{ |
|
|
|
|
MapID2NamedParam cache_map; |
|
|
|
|
CacheMapName2ParamTypeVal cacheMap; |
|
|
|
|
|
|
|
|
|
foreach(int id, _mapParameterId2Name[componentId].keys()) { |
|
|
|
|
const QString name(_mapParameterId2Name[componentId][id]); |
|
|
|
|
foreach(const QString& name, _mapParameterName2Variant[componentId].keys()) { |
|
|
|
|
const Fact *fact = _mapParameterName2Variant[componentId][name].value<Fact*>(); |
|
|
|
|
cache_map[id] = NamedParam(name, ParamTypeVal(fact->type(), fact->rawValue())); |
|
|
|
|
cacheMap[name] = ParamTypeVal(fact->type(), fact->rawValue()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QFile cache_file(parameterCacheFile(vehicleId, componentId)); |
|
|
|
|
cache_file.open(QIODevice::WriteOnly | QIODevice::Truncate); |
|
|
|
|
QFile cacheFile(parameterCacheFile(vehicleId, componentId)); |
|
|
|
|
cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate); |
|
|
|
|
|
|
|
|
|
QDataStream ds(&cache_file); |
|
|
|
|
ds << cache_map; |
|
|
|
|
QDataStream ds(&cacheFile); |
|
|
|
|
ds << cacheMap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QDir ParameterManager::parameterCacheDir() |
|
|
|
@ -758,46 +753,70 @@ QDir ParameterManager::parameterCacheDir()
@@ -758,46 +753,70 @@ QDir ParameterManager::parameterCacheDir()
|
|
|
|
|
|
|
|
|
|
QString ParameterManager::parameterCacheFile(int vehicleId, int componentId) |
|
|
|
|
{ |
|
|
|
|
return parameterCacheDir().filePath(QString("%1_%2").arg(vehicleId).arg(componentId)); |
|
|
|
|
return parameterCacheDir().filePath(QString("%1_%2.v2").arg(vehicleId).arg(componentId)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ParameterManager::_tryCacheHashLoad(int vehicleId, int componentId, QVariant hash_value) |
|
|
|
|
{ |
|
|
|
|
qCInfo(ParameterManagerLog) << "Attemping load from cache"; |
|
|
|
|
|
|
|
|
|
uint32_t crc32_value = 0; |
|
|
|
|
/* The datastructure of the cache table */ |
|
|
|
|
MapID2NamedParam cache_map; |
|
|
|
|
QFile cache_file(parameterCacheFile(vehicleId, componentId)); |
|
|
|
|
if (!cache_file.exists()) { |
|
|
|
|
CacheMapName2ParamTypeVal cacheMap; |
|
|
|
|
QFile cacheFile(parameterCacheFile(vehicleId, componentId)); |
|
|
|
|
if (!cacheFile.exists()) { |
|
|
|
|
/* no local cache, just wait for them to come in*/ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
cache_file.open(QIODevice::ReadOnly); |
|
|
|
|
cacheFile.open(QIODevice::ReadOnly); |
|
|
|
|
|
|
|
|
|
/* Deserialize the parameter cache table */ |
|
|
|
|
QDataStream ds(&cache_file); |
|
|
|
|
ds >> cache_map; |
|
|
|
|
QDataStream ds(&cacheFile); |
|
|
|
|
ds >> cacheMap; |
|
|
|
|
|
|
|
|
|
// Load parameter meta data for the version number stored in cache.
|
|
|
|
|
// We need meta data so we have access to the volatile bit
|
|
|
|
|
if (cacheMap.contains(_versionParam)) { |
|
|
|
|
_parameterSetMajorVersion = cacheMap[_versionParam].second.toInt(); |
|
|
|
|
} |
|
|
|
|
_loadMetaData(); |
|
|
|
|
|
|
|
|
|
/* compute the crc of the local cache to check against the remote */ |
|
|
|
|
|
|
|
|
|
foreach(int id, cache_map.keys()) { |
|
|
|
|
const QString name(cache_map[id].first); |
|
|
|
|
const void *vdat = cache_map[id].second.second.constData(); |
|
|
|
|
const FactMetaData::ValueType_t fact_type = static_cast<FactMetaData::ValueType_t>(cache_map[id].second.first); |
|
|
|
|
crc32_value = QGC::crc32((const uint8_t *)qPrintable(name), name.length(), crc32_value); |
|
|
|
|
crc32_value = QGC::crc32((const uint8_t *)vdat, FactMetaData::typeToSize(fact_type), crc32_value); |
|
|
|
|
FirmwarePlugin* firmwarePlugin = _vehicle->firmwarePlugin(); |
|
|
|
|
foreach (const QString& name, cacheMap.keys()) { |
|
|
|
|
bool volatileValue = false; |
|
|
|
|
|
|
|
|
|
FactMetaData* metaData = firmwarePlugin->getMetaDataForFact(_parameterMetaData, name, _vehicle->vehicleType()); |
|
|
|
|
if (metaData) { |
|
|
|
|
volatileValue = metaData->volatileValue(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (volatileValue) { |
|
|
|
|
// Does not take part in CRC
|
|
|
|
|
qCDebug(ParameterManagerLog) << "Volatile parameter" << name; |
|
|
|
|
} else { |
|
|
|
|
const ParamTypeVal& paramTypeVal = cacheMap[name]; |
|
|
|
|
const void *vdat = paramTypeVal.second.constData(); |
|
|
|
|
const FactMetaData::ValueType_t fact_type = static_cast<FactMetaData::ValueType_t>(paramTypeVal.first); |
|
|
|
|
crc32_value = QGC::crc32((const uint8_t *)qPrintable(name), name.length(), crc32_value); |
|
|
|
|
crc32_value = QGC::crc32((const uint8_t *)vdat, FactMetaData::typeToSize(fact_type), crc32_value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* if the two param set hashes match, just load from the disk */ |
|
|
|
|
if (crc32_value == hash_value.toUInt()) { |
|
|
|
|
qCInfo(ParameterManagerLog) << "Parameters loaded from cache" << qPrintable(QFileInfo(cache_file).absoluteFilePath()); |
|
|
|
|
/* if the two param set hashes match, just load from the disk */ |
|
|
|
|
int count = cache_map.count(); |
|
|
|
|
foreach(int id, cache_map.keys()) { |
|
|
|
|
const QString &name = cache_map[id].first; |
|
|
|
|
const QVariant &value = cache_map[id].second.second; |
|
|
|
|
const FactMetaData::ValueType_t fact_type = static_cast<FactMetaData::ValueType_t>(cache_map[id].second.first); |
|
|
|
|
qCInfo(ParameterManagerLog) << "Parameters loaded from cache" << qPrintable(QFileInfo(cacheFile).absoluteFilePath()); |
|
|
|
|
|
|
|
|
|
int count = cacheMap.count(); |
|
|
|
|
int index = 0; |
|
|
|
|
foreach (const QString& name, cacheMap.keys()) { |
|
|
|
|
const ParamTypeVal& paramTypeVal = cacheMap[name]; |
|
|
|
|
const FactMetaData::ValueType_t fact_type = static_cast<FactMetaData::ValueType_t>(paramTypeVal.first); |
|
|
|
|
const int mavType = _factTypeToMavType(fact_type); |
|
|
|
|
_parameterUpdate(vehicleId, componentId, name, count, id, mavType, value); |
|
|
|
|
_parameterUpdate(vehicleId, componentId, name, count, index++, mavType, paramTypeVal.second); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Return the hash value to notify we don't want any more updates
|
|
|
|
|
mavlink_param_set_t p; |
|
|
|
|
mavlink_param_union_t union_value; |
|
|
|
@ -836,7 +855,10 @@ void ParameterManager::_tryCacheHashLoad(int vehicleId, int componentId, QVarian
@@ -836,7 +855,10 @@ void ParameterManager::_tryCacheHashLoad(int vehicleId, int componentId, QVarian
|
|
|
|
|
|
|
|
|
|
ani->start(QAbstractAnimation::DeleteWhenStopped); |
|
|
|
|
} else { |
|
|
|
|
qCInfo(ParameterManagerLog) << "Parameters cache match failed" << qPrintable(QFileInfo(cache_file).absoluteFilePath()); |
|
|
|
|
// Cache parameter version may differ from vehicle parameter version so we can't trust information loaded from cache parameter version number
|
|
|
|
|
_parameterSetMajorVersion = -1; |
|
|
|
|
_clearMetaData(); |
|
|
|
|
qCInfo(ParameterManagerLog) << "Parameters cache match failed" << qPrintable(QFileInfo(cacheFile).absoluteFilePath()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -993,7 +1015,15 @@ FactMetaData::ValueType_t ParameterManager::_mavTypeToFactType(MAV_PARAM_TYPE ma
@@ -993,7 +1015,15 @@ FactMetaData::ValueType_t ParameterManager::_mavTypeToFactType(MAV_PARAM_TYPE ma
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ParameterManager::_addMetaDataToDefaultComponent(void) |
|
|
|
|
void ParameterManager::_clearMetaData(void) |
|
|
|
|
{ |
|
|
|
|
if (_parameterMetaData) { |
|
|
|
|
_parameterMetaData->deleteLater(); |
|
|
|
|
_parameterMetaData = NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ParameterManager::_loadMetaData(void) |
|
|
|
|
{ |
|
|
|
|
if (_parameterMetaData) { |
|
|
|
|
return; |
|
|
|
@ -1004,9 +1034,18 @@ void ParameterManager::_addMetaDataToDefaultComponent(void)
@@ -1004,9 +1034,18 @@ void ParameterManager::_addMetaDataToDefaultComponent(void)
|
|
|
|
|
|
|
|
|
|
// Load best parameter meta data set
|
|
|
|
|
metaDataFile = parameterMetaDataFile(_vehicle, _vehicle->firmwareType(), _parameterSetMajorVersion, majorVersion, minorVersion); |
|
|
|
|
qCDebug(ParameterManagerLog) << "Adding meta data to Vehicle file:major:minor" << metaDataFile << majorVersion << minorVersion; |
|
|
|
|
|
|
|
|
|
qCDebug(ParameterManagerLog) << "Loading meta data file:major:minor" << metaDataFile << majorVersion << minorVersion; |
|
|
|
|
_parameterMetaData = _vehicle->firmwarePlugin()->loadParameterMetaData(metaDataFile); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ParameterManager::_addMetaDataToDefaultComponent(void) |
|
|
|
|
{ |
|
|
|
|
_loadMetaData(); |
|
|
|
|
|
|
|
|
|
if (_metaDataAddedToFacts) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
_metaDataAddedToFacts = true; |
|
|
|
|
|
|
|
|
|
// Loop over all parameters in default component adding meta data
|
|
|
|
|
QVariantMap& factMap = _mapParameterName2Variant[_vehicle->defaultComponentId()]; |
|
|
|
|