FactLoader.cc 6.55 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/*=====================================================================
 
 QGroundControl Open Source Ground Control Station
 
 (c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 
 This file is part of the QGROUNDCONTROL project
 
 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
 
 ======================================================================*/

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "FactLoader.h"
#include "QGCApplication.h"

#include <QFile>
#include <QDebug>

Q_LOGGING_CATEGORY(FactLoaderLog, "FactLoaderLog")

FactLoader::FactLoader(UASInterface* uas, QObject* parent) :
    QObject(parent),
    _lastSeenComponent(-1),
    _paramMgr(NULL),
    _factsReady(false)
{
    Q_ASSERT(uas);

    _uasId = uas->getUASID();
    
    _paramMgr = uas->getParamManager();
    Q_ASSERT(_paramMgr);
    
    // We need to be initialized before param mgr starts sending parameters so we catch each one
    Q_ASSERT(!_paramMgr->parametersReady());
    
    // We need to know when the param mgr is done sending the initial set of paramters
    connect(_paramMgr, SIGNAL(parameterListUpToDate()), this, SLOT(_paramMgrParameterListUpToDate()));
    
54 55
    // We track parameters changes to keep Facts up to date.
    connect(uas, &UASInterface::parameterUpdate, this, &FactLoader::_parameterUpdate);
56 57 58 59
}

FactLoader::~FactLoader()
{
Don Gagne's avatar
Don Gagne committed
60

61 62
}

63 64
/// Called whenever a parameter is updated or first seen.
void FactLoader::_parameterUpdate(int uas, int component, QString parameterName, int mavType, QVariant value)
65 66 67 68 69 70 71 72 73 74 75 76 77
{
    // Is this for our uas?
    if (uas != _uasId) {
        return;
    }
    
    if (_lastSeenComponent == -1) {
        _lastSeenComponent = component;
    } else {
        // Code cannot handle parameters coming form different components yets
        Q_ASSERT(component == _lastSeenComponent);
    }
    
Don Gagne's avatar
Don Gagne committed
78
    bool setMetaData = false;
79
    if (!_mapParameterName2Variant.contains(parameterName)) {
Don Gagne's avatar
Don Gagne committed
80 81
        qCDebug(FactLoaderLog) << "Adding new fact" << parameterName;
        
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
        FactMetaData::ValueType_t factType;
        switch (mavType) {
            case MAV_PARAM_TYPE_UINT8:
                factType = FactMetaData::valueTypeUint8;
                break;
            case MAV_PARAM_TYPE_INT8:
                factType = FactMetaData::valueTypeUint8;
                break;
            case MAV_PARAM_TYPE_UINT16:
                factType = FactMetaData::valueTypeUint16;
                break;
            case MAV_PARAM_TYPE_INT16:
                factType = FactMetaData::valueTypeInt16;
                break;
            case MAV_PARAM_TYPE_UINT32:
                factType = FactMetaData::valueTypeUint32;
                break;
            case MAV_PARAM_TYPE_INT32:
                factType = FactMetaData::valueTypeInt32;
                break;
            case MAV_PARAM_TYPE_REAL32:
                factType = FactMetaData::valueTypeFloat;
                break;
            case MAV_PARAM_TYPE_REAL64:
                factType = FactMetaData::valueTypeDouble;
                break;
            default:
                factType = FactMetaData::valueTypeInt32;
                qCritical() << "Unsupported fact type" << mavType;
                break;
        }
        
        Fact* fact = new Fact(parameterName, factType, this);
Don Gagne's avatar
Don Gagne committed
115
        setMetaData = true;
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
        
        _mapParameterName2Variant[parameterName] = QVariant::fromValue(fact);
        _mapFact2ParameterName[fact] = parameterName;
        
        // 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);
    }
    
    Q_ASSERT(_mapParameterName2Variant.contains(parameterName));
    
    qCDebug(FactLoaderLog) << "Updating fact value" << parameterName << value;
    
    Fact* fact = _mapParameterName2Variant[parameterName].value<Fact*>();
    Q_ASSERT(fact);
    fact->_containerSetValue(value);
Don Gagne's avatar
Don Gagne committed
131 132 133 134
    
    if (setMetaData) {
        _addMetaDataToFact(fact);
    }
135 136 137 138
}

/// Connected to Fact::valueUpdated
///
Don Gagne's avatar
Don Gagne committed
139
/// Sets the new value into the Parameter Manager. Parameter is persisted after send.
Don Gagne's avatar
Don Gagne committed
140
void FactLoader::_valueUpdated(const QVariant& value)
141 142 143 144 145 146 147 148 149 150 151 152 153
{
    Fact* fact = qobject_cast<Fact*>(sender());
    Q_ASSERT(fact);
    
    Q_ASSERT(_lastSeenComponent != -1);
    Q_ASSERT(_paramMgr);
    Q_ASSERT(_mapFact2ParameterName.contains(fact));
    
    QVariant typedValue;
    switch (fact->type()) {
        case FactMetaData::valueTypeInt8:
        case FactMetaData::valueTypeInt16:
        case FactMetaData::valueTypeInt32:
Don Gagne's avatar
Don Gagne committed
154 155
            typedValue.setValue(QVariant(value.toInt()));
            break;
156 157 158 159
            
        case FactMetaData::valueTypeUint8:
        case FactMetaData::valueTypeUint16:
        case FactMetaData::valueTypeUint32:
Don Gagne's avatar
Don Gagne committed
160
            typedValue.setValue(value.toUInt());
161 162 163
            break;
            
        case FactMetaData::valueTypeFloat:
Don Gagne's avatar
Don Gagne committed
164
            typedValue.setValue(value.toFloat());
165 166 167
            break;
            
        case FactMetaData::valueTypeDouble:
Don Gagne's avatar
Don Gagne committed
168
            typedValue.setValue(value.toDouble());
169 170 171
            break;
    }
    
Don Gagne's avatar
Don Gagne committed
172 173
    qCDebug(FactLoaderLog) << "Set parameter" << fact->name() << typedValue;

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
    _paramMgr->setParameter(_lastSeenComponent, _mapFact2ParameterName[fact], typedValue);
    _paramMgr->sendPendingParameters(true /* persistAfterSend */, false /* forceSend */);
}

// Called when param mgr list is up to date
void FactLoader::_paramMgrParameterListUpToDate(void)
{
    if (!_factsReady) {
        _factsReady = true;
        
        // We don't need this any more
        disconnect(_paramMgr, SIGNAL(parameterListUpToDate()), this, SLOT(_paramMgrParameterListUpToDate()));

        // There may be parameterUpdated signals still in our queue. Flush them out.
        qgcApp()->processEvents();
        
        // We should have all paramters now so we can signal ready
        emit factsReady();
    }
}
Don Gagne's avatar
Don Gagne committed
194 195 196 197

void FactLoader::_addMetaDataToFact(Fact* fact)
{
    FactMetaData* metaData = new FactMetaData(this);
198
    metaData->initFromTypeOnly(fact->type());
Don Gagne's avatar
Don Gagne committed
199
}