Commit 4bfb3701 authored by Don Gagne's avatar Don Gagne

Switched to ParameterLoader, added component id support

parent 4b128fba
...@@ -776,7 +776,7 @@ HEADERS += \ ...@@ -776,7 +776,7 @@ HEADERS += \
src/FactSystem/FactBinder.h \ src/FactSystem/FactBinder.h \
src/FactSystem/FactMetaData.h \ src/FactSystem/FactMetaData.h \
src/FactSystem/FactValidator.h \ src/FactSystem/FactValidator.h \
src/FactSystem/FactLoader.h \ src/FactSystem/ParameterLoader.h \
SOURCES += \ SOURCES += \
src/FactSystem/FactSystem.cc \ src/FactSystem/FactSystem.cc \
...@@ -784,4 +784,4 @@ SOURCES += \ ...@@ -784,4 +784,4 @@ SOURCES += \
src/FactSystem/FactBinder.cc \ src/FactSystem/FactBinder.cc \
src/FactSystem/FactMetaData.cc \ src/FactSystem/FactMetaData.cc \
src/FactSystem/FactValidator.cc \ src/FactSystem/FactValidator.cc \
src/FactSystem/FactLoader.cc \ src/FactSystem/ParameterLoader.cc \
...@@ -24,20 +24,20 @@ ...@@ -24,20 +24,20 @@
/// @file /// @file
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
#include "FactLoader.h" #include "ParameterLoader.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#include "QGCLoggingCategory.h" #include "QGCLoggingCategory.h"
#include <QFile> #include <QFile>
#include <QDebug> #include <QDebug>
QGC_LOGGING_CATEGORY(FactLoaderLog, "FactLoaderLog") QGC_LOGGING_CATEGORY(ParameterLoaderLog, "ParameterLoaderLog")
FactLoader::FactLoader(UASInterface* uas, QObject* parent) : ParameterLoader::ParameterLoader(UASInterface* uas, QObject* parent) :
QObject(parent), QObject(parent),
_lastSeenComponent(-1),
_paramMgr(NULL), _paramMgr(NULL),
_factsReady(false) _parametersReady(false),
_defaultComponentId(FactSystem::defaultComponentId)
{ {
Q_ASSERT(uas); Q_ASSERT(uas);
...@@ -53,32 +53,37 @@ FactLoader::FactLoader(UASInterface* uas, QObject* parent) : ...@@ -53,32 +53,37 @@ FactLoader::FactLoader(UASInterface* uas, QObject* parent) :
connect(_paramMgr, SIGNAL(parameterListUpToDate()), this, SLOT(_paramMgrParameterListUpToDate())); connect(_paramMgr, SIGNAL(parameterListUpToDate()), this, SLOT(_paramMgrParameterListUpToDate()));
// We track parameters changes to keep Facts up to date. // We track parameters changes to keep Facts up to date.
connect(uas, &UASInterface::parameterUpdate, this, &FactLoader::_parameterUpdate); connect(uas, &UASInterface::parameterUpdate, this, &ParameterLoader::_parameterUpdate);
} }
FactLoader::~FactLoader() ParameterLoader::~ParameterLoader()
{ {
} }
/// Called whenever a parameter is updated or first seen. /// Called whenever a parameter is updated or first seen.
void FactLoader::_parameterUpdate(int uas, int component, QString parameterName, int mavType, QVariant value) void ParameterLoader::_parameterUpdate(int uas, int componentId, QString parameterName, int mavType, QVariant value)
{ {
bool setMetaData = false;
// Is this for our uas? // Is this for our uas?
if (uas != _uasId) { if (uas != _uasId) {
return; return;
} }
if (_lastSeenComponent == -1) { // Attempt to determine default component id
_lastSeenComponent = component; if (_defaultComponentId == FactSystem::defaultComponentId && _defaultComponentIdParam.isEmpty()) {
} else { _defaultComponentIdParam = getDefaultComponentIdParam();
// Code cannot handle parameters coming form different components yets }
Q_ASSERT(component == _lastSeenComponent); if (!_defaultComponentIdParam.isEmpty() && _defaultComponentIdParam == parameterName) {
_defaultComponentId = componentId;
} }
bool setMetaData = false; if (!_mapParameterName2Variant.contains(componentId) || !_mapParameterName2Variant[componentId].contains(parameterName)) {
if (!_mapParameterName2Variant.contains(parameterName)) { // These should not get our of sync
qCDebug(FactLoaderLog) << "Adding new fact" << parameterName; Q_ASSERT(_mapParameterName2Variant.contains(componentId) == _mapFact2ParameterName.contains(componentId));
qCDebug(ParameterLoaderLog) << "Adding new fact (component:" << componentId << "name:" << parameterName << ")";
FactMetaData::ValueType_t factType; FactMetaData::ValueType_t factType;
switch (mavType) { switch (mavType) {
...@@ -112,21 +117,21 @@ void FactLoader::_parameterUpdate(int uas, int component, QString parameterName, ...@@ -112,21 +117,21 @@ void FactLoader::_parameterUpdate(int uas, int component, QString parameterName,
break; break;
} }
Fact* fact = new Fact(parameterName, factType, this); Fact* fact = new Fact(componentId, parameterName, factType, this);
setMetaData = true; setMetaData = true;
_mapParameterName2Variant[parameterName] = QVariant::fromValue(fact); _mapParameterName2Variant[componentId][parameterName] = QVariant::fromValue(fact);
_mapFact2ParameterName[fact] = parameterName; _mapFact2ParameterName[componentId][fact] = parameterName;
// We need to know when the fact changes from QML so that we can send the new value to the parameter manager // We need to know when the fact changes from QML so that we can send the new value to the parameter manager
connect(fact, &Fact::_containerValueChanged, this, &FactLoader::_valueUpdated); connect(fact, &Fact::_containerValueChanged, this, &ParameterLoader::_valueUpdated);
} }
Q_ASSERT(_mapParameterName2Variant.contains(parameterName)); Q_ASSERT(_mapParameterName2Variant[componentId].contains(parameterName));
qCDebug(FactLoaderLog) << "Updating fact value" << parameterName << value; qCDebug(ParameterLoaderLog) << "Updating fact value (component:" << componentId << "name:" << parameterName << value << ")";
Fact* fact = _mapParameterName2Variant[parameterName].value<Fact*>(); Fact* fact = _mapParameterName2Variant[componentId][parameterName].value<Fact*>();
Q_ASSERT(fact); Q_ASSERT(fact);
fact->_containerSetValue(value); fact->_containerSetValue(value);
...@@ -138,14 +143,16 @@ void FactLoader::_parameterUpdate(int uas, int component, QString parameterName, ...@@ -138,14 +143,16 @@ void FactLoader::_parameterUpdate(int uas, int component, QString parameterName,
/// Connected to Fact::valueUpdated /// Connected to Fact::valueUpdated
/// ///
/// Sets the new value into the Parameter Manager. Parameter is persisted after send. /// Sets the new value into the Parameter Manager. Parameter is persisted after send.
void FactLoader::_valueUpdated(const QVariant& value) void ParameterLoader::_valueUpdated(const QVariant& value)
{ {
Fact* fact = qobject_cast<Fact*>(sender()); Fact* fact = qobject_cast<Fact*>(sender());
Q_ASSERT(fact); Q_ASSERT(fact);
Q_ASSERT(_lastSeenComponent != -1); int componentId = fact->componentId();
Q_ASSERT(_paramMgr); Q_ASSERT(_paramMgr);
Q_ASSERT(_mapFact2ParameterName.contains(fact)); Q_ASSERT(_mapFact2ParameterName.contains(componentId));
Q_ASSERT(_mapFact2ParameterName[componentId].contains(fact));
QVariant typedValue; QVariant typedValue;
switch (fact->type()) { switch (fact->type()) {
...@@ -170,17 +177,17 @@ void FactLoader::_valueUpdated(const QVariant& value) ...@@ -170,17 +177,17 @@ void FactLoader::_valueUpdated(const QVariant& value)
break; break;
} }
qCDebug(FactLoaderLog) << "Set parameter" << fact->name() << typedValue; qCDebug(ParameterLoaderLog) << "Set parameter (componentId:" << componentId << "name:" << fact->name() << typedValue << ")";
_paramMgr->setParameter(_lastSeenComponent, _mapFact2ParameterName[fact], typedValue); _paramMgr->setParameter(componentId, fact->name(), typedValue);
_paramMgr->sendPendingParameters(true /* persistAfterSend */, false /* forceSend */); _paramMgr->sendPendingParameters(true /* persistAfterSend */, false /* forceSend */);
} }
// Called when param mgr list is up to date // Called when param mgr list is up to date
void FactLoader::_paramMgrParameterListUpToDate(void) void ParameterLoader::_paramMgrParameterListUpToDate(void)
{ {
if (!_factsReady) { if (!_parametersReady) {
_factsReady = true; _parametersReady = true;
// We don't need this any more // We don't need this any more
disconnect(_paramMgr, SIGNAL(parameterListUpToDate()), this, SLOT(_paramMgrParameterListUpToDate())); disconnect(_paramMgr, SIGNAL(parameterListUpToDate()), this, SLOT(_paramMgrParameterListUpToDate()));
...@@ -188,13 +195,88 @@ void FactLoader::_paramMgrParameterListUpToDate(void) ...@@ -188,13 +195,88 @@ void FactLoader::_paramMgrParameterListUpToDate(void)
// There may be parameterUpdated signals still in our queue. Flush them out. // There may be parameterUpdated signals still in our queue. Flush them out.
qgcApp()->processEvents(); qgcApp()->processEvents();
// We should have all paramters now so we can signal ready _determineDefaultComponentId();
emit factsReady();
// We should have all parameters now so we can signal ready
emit parametersReady();
} }
} }
void FactLoader::_addMetaDataToFact(Fact* fact) void ParameterLoader::_addMetaDataToFact(Fact* fact)
{ {
FactMetaData* metaData = new FactMetaData(this); FactMetaData* metaData = new FactMetaData(this);
metaData->initFromTypeOnly(fact->type()); metaData->initFromTypeOnly(fact->type());
} }
void ParameterLoader::refreshAllParameters(void)
{
Q_ASSERT(_paramMgr);
_paramMgr->requestParameterList();
}
void ParameterLoader::_determineDefaultComponentId(void)
{
if (_defaultComponentId == FactSystem::defaultComponentId) {
// We don't have a default component id yet. That means the plugin can't provide
// the param to trigger off of. Instead we use the most prominent component id in
// the set of parameters. Better than nothing!
_defaultComponentId = -1;
foreach(int componentId, _mapParameterName2Variant.keys()) {
if (_mapParameterName2Variant[componentId].count() > _defaultComponentId) {
_defaultComponentId = componentId;
}
}
Q_ASSERT(_defaultComponentId != -1);
}
}
/// Translates FactSystem::defaultComponentId to real component id if needed
int ParameterLoader::_actualComponentId(int componentId)
{
if (componentId == FactSystem::defaultComponentId) {
componentId = _defaultComponentId;
Q_ASSERT(componentId != FactSystem::defaultComponentId);
}
return componentId;
}
void ParameterLoader::refreshParameter(int componentId, const QString& name)
{
Q_ASSERT(_paramMgr);
_paramMgr->requestParameterUpdate(_actualComponentId(componentId), name);
}
void ParameterLoader::refreshParametersPrefix(int componentId, const QString& namePrefix)
{
Q_ASSERT(_paramMgr);
componentId = _actualComponentId(componentId);
Q_ASSERT(_mapFact2ParameterName.contains(componentId));
foreach(QString name, _mapParameterName2Variant[componentId].keys()) {
if (name.startsWith(namePrefix)) {
refreshParameter(componentId, name);
}
}
}
bool ParameterLoader::factExists(int componentId, const QString& name)
{
componentId = _actualComponentId(componentId);
if (_mapParameterName2Variant.contains(componentId)) {
return _mapParameterName2Variant[componentId].contains(name);
}
return false;
}
Fact* ParameterLoader::getFact(int componentId, const QString& name)
{
componentId = _actualComponentId(componentId);
Q_ASSERT(_mapParameterName2Variant.contains(componentId));
Q_ASSERT(_mapParameterName2Variant[componentId].contains(name));
Fact* fact = _mapParameterName2Variant[componentId][name].value<Fact*>();
Q_ASSERT(fact);
return fact;
}
...@@ -21,42 +21,62 @@ ...@@ -21,42 +21,62 @@
======================================================================*/ ======================================================================*/
#ifndef FactLoader_h #ifndef PARAMETERLOADER_H
#define FactLoader_h #define PARAMETERLOADER_H
#include <QObject> #include <QObject>
#include <QMap> #include <QMap>
#include <QXmlStreamReader> #include <QXmlStreamReader>
#include <QLoggingCategory> #include <QLoggingCategory>
#include "Fact.h" #include "FactSystem.h"
#include "UASInterface.h" #include "UASInterface.h"
/// @file /// @file
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
Q_DECLARE_LOGGING_CATEGORY(FactLoaderLog) Q_DECLARE_LOGGING_CATEGORY(ParameterLoaderLog)
/// Connects to Parameter Manager to load/update Facts /// Connects to Parameter Manager to load/update Facts
class FactLoader : public QObject class ParameterLoader : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
/// @param uas Uas which this set of facts is associated with /// @param uas Uas which this set of facts is associated with
FactLoader(UASInterface* uas, QObject* parent = NULL); ParameterLoader(UASInterface* uas, QObject* parent = NULL);
~FactLoader(); ~ParameterLoader();
/// Returns true if the full set of facts are ready /// Returns true if the full set of facts are ready
bool factsAreReady(void) { return _factsReady; } bool parametersAreReady(void) { return _parametersReady; }
/// Returns the fact QVariantMap /// Re-request the full set of parameters from the autopilot
const QVariantMap& factMap(void) { return _mapParameterName2Variant; } void refreshAllParameters(void);
/// Request a refresh on the specific parameter
void refreshParameter(int componentId, const QString& name);
/// Request a refresh on all parameters that begin with the specified prefix
void refreshParametersPrefix(int componentId, const QString& namePrefix);
/// Returns true if the specifed fact exists
bool factExists(int componentId, ///< fact component, -1=default component
const QString& name); ///< fact name
/// Returns the specified Fact.
/// WARNING: Will assert if fact does not exists. If that possibily exists, check for existince first with
/// factExists.
Fact* getFact(int componentId, ///< fact component, -1=default component
const QString& name); ///< fact name
/// Return the parameter for which the default component id is derived from. Return an empty
/// string is this is not available.
virtual QString getDefaultComponentIdParam(void) const = 0;
signals: signals:
/// Signalled when the full set of facts are ready /// Signalled when the full set of facts are ready
void factsReady(void); void parametersReady(void);
protected: protected:
/// Base implementation adds generic meta data based on variant type. Derived class can override to provide /// Base implementation adds generic meta data based on variant type. Derived class can override to provide
...@@ -64,23 +84,30 @@ protected: ...@@ -64,23 +84,30 @@ protected:
virtual void _addMetaDataToFact(Fact* fact); virtual void _addMetaDataToFact(Fact* fact);
private slots: private slots:
void _parameterUpdate(int uas, int component, QString parameterName, int mavType, QVariant value); void _parameterUpdate(int uas, int componentId, QString parameterName, int mavType, QVariant value);
void _valueUpdated(const QVariant& value); void _valueUpdated(const QVariant& value);
void _paramMgrParameterListUpToDate(void); void _paramMgrParameterListUpToDate(void);
private: private:
static QVariant _stringToTypedVariant(const QString& string, FactMetaData::ValueType_t type, bool failOk = false); static QVariant _stringToTypedVariant(const QString& string, FactMetaData::ValueType_t type, bool failOk = false);
int _actualComponentId(int componentId);
void _determineDefaultComponentId(void);
QMap<Fact*, QString> _mapFact2ParameterName; ///< Maps from a Fact to a parameter name /// First mapping is by component id
/// Second mapping is parameter name, to Fact
QMap<int, QMap<Fact*, QString> > _mapFact2ParameterName;
int _uasId; ///< Id for uas which this set of Facts are associated with int _uasId; ///< Id for uas which this set of Facts are associated with
int _lastSeenComponent;
QGCUASParamManagerInterface* _paramMgr; QGCUASParamManagerInterface* _paramMgr;
QVariantMap _mapParameterName2Variant; /// First mapping id\s by component id
/// Second mapping is parameter name, to Fact* in QVariant
QMap<int, QVariantMap> _mapParameterName2Variant;
bool _factsReady; ///< All facts received from param mgr bool _parametersReady; ///< All params received from param mgr
int _defaultComponentId;
QString _defaultComponentIdParam;
}; };
#endif #endif
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment