void UAVObjectUtilManager::saveNextObject()
{
    if (queue.isEmpty()) {
        return;
    }

    Q_ASSERT(saveState == IDLE);

    // Get next object from the queue
    UAVObject *obj = queue.head();
    qDebug() << "Send save object request to board " << obj->getName();

    ObjectPersistence *objper = dynamic_cast<ObjectPersistence *>(getObjectManager()->getObject(ObjectPersistence::NAME));
    connect(objper, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(objectPersistenceTransactionCompleted(UAVObject *, bool)));
    connect(objper, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(objectPersistenceUpdated(UAVObject *)));
    saveState = AWAITING_ACK;
    if (obj != NULL) {
        ObjectPersistence::DataFields data;
        data.Operation  = ObjectPersistence::OPERATION_SAVE;
        data.Selection  = ObjectPersistence::SELECTION_SINGLEOBJECT;
        data.ObjectID   = obj->getObjID();
        data.InstanceID = obj->getInstID();
        objper->setData(data);
        objper->updated();
    }
    // Now: we are going to get two "objectUpdated" messages (one coming from GCS, one coming from Flight, which
    // will confirm the object was properly received by both sides) and then one "transactionCompleted" indicating
    // that the Flight side did not only receive the object but it did receive it without error. Last we will get
    // a last "objectUpdated" message coming from flight side, where we'll get the results of the objectPersistence
    // operation we asked for (saved, other).
}
void ConfigStabilizationWidget::restoreStabBank(int bank)
{
    UAVObject *stabBankObject = getStabBankObject(bank);

    if (stabBankObject) {
        ObjectPersistence *objectPersistenceObject = ObjectPersistence::GetInstance(getObjectManager());
        QTimer updateTimer(this);
        QEventLoop eventLoop(this);
        connect(&updateTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
        connect(objectPersistenceObject, SIGNAL(objectUpdated(UAVObject *)), &eventLoop, SLOT(quit()));

        ObjectPersistence::DataFields data;
        data.Operation  = ObjectPersistence::OPERATION_LOAD;
        data.Selection  = ObjectPersistence::SELECTION_SINGLEOBJECT;
        data.ObjectID   = stabBankObject->getObjID();
        data.InstanceID = stabBankObject->getInstID();
        objectPersistenceObject->setData(data);
        objectPersistenceObject->updated();
        updateTimer.start(500);
        eventLoop.exec();
        if (updateTimer.isActive()) {
            stabBankObject->requestUpdate();
        }
        updateTimer.stop();
    }
}
/**
 * @brief UAVObjectUtilManager::saveNextObject
 *
 * Processes the save queue.
 */
void UAVObjectUtilManager::saveNextObject()
{
    if ( queue.isEmpty() ) {
        return;
    }

    Q_ASSERT(saveState == IDLE);

    // Get next object from the queue (don't dequeue yet)
    UAVObject* obj = queue.head();
    Q_ASSERT(obj);
    qDebug() << "Send save object request to board " << obj->getName();

    ObjectPersistence * objectPersistence = ObjectPersistence::GetInstance(getObjectManager());
    Q_ASSERT(objectPersistence);

    // "transactionCompleted" is emitted once the objectPersistence object is sent over the telemetry link.
    // Since its metadata state that it should be ACK'ed on flight telemetry, the transactionCompleted signal
    // will be triggered once the GCS telemetry manager receives an ACK from the flight controller, or times
    // out. the success value will reflect success or failure.
    connect(objectPersistence, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(objectPersistenceTransactionCompleted(UAVObject*,bool)));
    // After we update the objectPersistence UAVO, we need to listen to its "objectUpdated" event, which will occur
    // once the flight controller sends this object back to the GCS, with the "Operation" field set to "Completed"
    // or "Error".
    connect(objectPersistence, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(objectPersistenceUpdated(UAVObject *)));
    saveState = AWAITING_ACK;
    qDebug() << "[saveObjectToFlash] Moving on to AWAITING_ACK";

    ObjectPersistence::DataFields data;
    data.Operation = ObjectPersistence::OPERATION_SAVE;
    data.Selection = ObjectPersistence::SELECTION_SINGLEOBJECT;
    data.ObjectID = obj->getObjID();
    data.InstanceID = obj->getInstID();
    objectPersistence->setData(data);
    objectPersistence->updated();
    // Now: we are going to get the following:
    // - two "objectUpdated" messages (one coming from GCS, one coming from Flight, which will confirm the object
    //   was properly received by both sides). This is because the metadata of objectPersistence has "FlightUpdateOnChange"
    //   set to true.
    //  - then one "transactionCompleted" indicating that the Flight side did not only receive the object but it did
    //    receive it without error (that message will be triggered by reception of the ACK).
    //  - Last we will get one last "objectUpdated" message coming from flight side, where we'll get the results of
    //    the objectPersistence operation we asked for (saved, other).
}