1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-26 15:54:15 +01:00

GCS/UAVObjects: Added support for saving and loading of objects

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@407 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
vassilis 2010-03-28 22:22:19 +00:00 committed by vassilis
parent df573fdad5
commit 37cec4c7fd
16 changed files with 360 additions and 38 deletions

View File

@ -32,7 +32,7 @@
const QString ExampleObject::NAME = QString("ExampleObject"); const QString ExampleObject::NAME = QString("ExampleObject");
ExampleObject::ExampleObject(): UAVDataObject(OBJID, SINGLEINST, NAME) ExampleObject::ExampleObject(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
{ {
// Create fields // Create fields
QList<UAVObjectField*> fields; QList<UAVObjectField*> fields;

View File

@ -46,7 +46,8 @@ public:
static const quint32 OBJID = 3048370380U; static const quint32 OBJID = 3048370380U;
static const QString NAME; static const QString NAME;
static const bool SINGLEINST = 0; static const bool ISSINGLEINST = 0;
static const bool ISSETTINGS = 0;
static const quint32 NUMBYTES = sizeof(DataFields); static const quint32 NUMBYTES = sizeof(DataFields);
ExampleObject(); ExampleObject();

View File

@ -0,0 +1,81 @@
/**
******************************************************************************
*
* @file examplesettings.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Implementation of the ExampleSettings object. This file has been
* automatically generated by the UAVObjectGenerator.
*
* @note Object definition file: examplesettings.xml.
* This is an automatically generated file.
* DO NOT modify manually.
*
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "examplesettings.h"
const QString ExampleSettings::NAME = QString("ExampleSettings");
ExampleSettings::ExampleSettings(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
{
// Create fields
QList<UAVObjectField*> fields;
fields.append(new UAVObjectField(QString("setting1"), QString("unit1"), UAVObjectField::FIELDTYPE_INT8, 1));
fields.append(new UAVObjectField(QString("setting2"), QString("unit2"), UAVObjectField::FIELDTYPE_INT16, 1));
fields.append(new UAVObjectField(QString("setting3"), QString("unit3"), UAVObjectField::FIELDTYPE_INT8, 1));
fields.append(new UAVObjectField(QString("setting4"), QString("unit4"), UAVObjectField::FIELDTYPE_INT32, 1));
// Initialize object
initializeFields(fields, (quint8*)&data, NUMBYTES);
}
UAVObject::Metadata ExampleSettings::getDefaultMetadata()
{
UAVObject::Metadata metadata;
metadata.gcsTelemetryAcked = 1;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.flightTelemetryAcked = 1;
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
metadata.flightTelemetryUpdatePeriod = 0;
metadata.loggingUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.loggingUpdatePeriod = 0;
return metadata;
}
ExampleSettings::DataFields ExampleSettings::getData()
{
QMutexLocker locker(mutex);
return data;
}
void ExampleSettings::setData(DataFields& data)
{
QMutexLocker locker(mutex);
this->data = data;
emit objectUpdatedAuto(this); // trigger object updated event
emit objectUpdated(this);
}
UAVDataObject* ExampleSettings::clone(quint32 instID)
{
ExampleSettings* obj = new ExampleSettings();
obj->initialize(instID, this->getMetaObject());
return obj;
}

View File

@ -0,0 +1,65 @@
/**
******************************************************************************
*
* @file examplesettings.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Implementation of the ExampleSettings object. This file has been
* automatically generated by the UAVObjectGenerator.
*
* @note Object definition file: examplesettings.xml.
* This is an automatically generated file.
* DO NOT modify manually.
*
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EXAMPLESETTINGS_H
#define EXAMPLESETTINGS_H
#include "uavdataobject.h"
class ExampleSettings: public UAVDataObject
{
public:
typedef struct {
qint8 setting1;
qint16 setting2;
qint8 setting3;
qint32 setting4;
} __attribute__((packed)) DataFields;
static const quint32 OBJID = 3555345034U;
static const QString NAME;
static const bool ISSINGLEINST = 1;
static const bool ISSETTINGS = 1;
static const quint32 NUMBYTES = sizeof(DataFields);
ExampleSettings();
DataFields getData();
void setData(DataFields& data);
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
private:
DataFields data;
};
#endif // EXAMPLESETTINGS_H

View File

@ -8,7 +8,7 @@ UAVObjectsTest::UAVObjectsTest(): sout(stdout), done(false)
connect(objMngr, SIGNAL(newInstance(UAVObject*)), this, SLOT(newInstance(UAVObject*))); connect(objMngr, SIGNAL(newInstance(UAVObject*)), this, SLOT(newInstance(UAVObject*)));
// Create test objects // Create test objects
obj1 = new TestObject1(); obj1 = new ExampleObject();
connect(obj1, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(objectUpdated(UAVObject*))); connect(obj1, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(objectUpdated(UAVObject*)));
connect(obj1, SIGNAL(objectUpdatedAuto(UAVObject*)), this, SLOT(objectUpdatedAuto(UAVObject*))); connect(obj1, SIGNAL(objectUpdatedAuto(UAVObject*)), this, SLOT(objectUpdatedAuto(UAVObject*)));
connect(obj1, SIGNAL(objectUpdatedManual(UAVObject*)), this, SLOT(objectUpdatedManual(UAVObject*))); connect(obj1, SIGNAL(objectUpdatedManual(UAVObject*)), this, SLOT(objectUpdatedManual(UAVObject*)));
@ -62,16 +62,16 @@ void UAVObjectsTest::runTest()
if (!done) if (!done)
{ {
// Create a new instance // Create a new instance
TestObject1* obj2 = new TestObject1(); ExampleObject* obj2 = new ExampleObject();
objMngr->registerObject(obj2); objMngr->registerObject(obj2);
// Set data // Set data
TestObject1::DataFields data = obj1->getData(); ExampleObject::DataFields data = obj1->getData();
data.field1 = 1; data.field1 = 1;
data.field2[0] = 2.1; data.field3[0] = 2.1;
data.field2[1] = 2.2; data.field3[1] = 2.2;
data.field2[2] = 2.3; data.field3[2] = 2.3;
data.field3 = 3; data.field2 = 3;
data.field4 = 4; data.field4 = 4;
obj1->setData(data); obj1->setData(data);
@ -93,16 +93,27 @@ void UAVObjectsTest::runTest()
quint8* buf = new quint8[obj1->getNumBytes()]; quint8* buf = new quint8[obj1->getNumBytes()];
obj1->pack(buf); obj1->pack(buf);
data.field1 = 10; data.field1 = 10;
data.field2[0] = 20.1; data.field3[0] = 20.1;
data.field2[1] = 20.2; data.field3[1] = 20.2;
data.field2[2] = 20.3; data.field3[2] = 20.3;
data.field3 = 30; data.field2 = 30;
data.field4 = 40; data.field4 = 40;
obj1->setData(data); obj1->setData(data);
obj1->unpack(buf); obj1->unpack(buf);
// Save, load testing
obj1->save();
data.field1 = 10;
data.field3[0] = 20.1;
data.field3[1] = 20.2;
data.field3[2] = 20.3;
data.field2 = 30;
data.field4 = 40;
obj1->setData(data);
obj1->load();
// Get all instances // Get all instances
QList<UAVObject*> objs = objMngr->getObjectInstances(TestObject1::OBJID); QList<UAVObject*> objs = objMngr->getObjectInstances(ExampleObject::OBJID);
for (int n = 0; n < objs.length(); ++n) for (int n = 0; n < objs.length(); ++n)
{ {
sout << "[Printing object instances]\n"; sout << "[Printing object instances]\n";

View File

@ -1,8 +1,8 @@
#ifndef UAVOBJECTSTEST_H #ifndef UAVOBJECTSTEST_H
#define UAVOBJECTSTEST_H #define UAVOBJECTSTEST_H
#include "..\UAVObjectManager.h" #include "..\uavobjectmanager.h"
#include "testobject1.h" #include "..\exampleobject.h"
#include <QTimer> #include <QTimer>
#include <QTextStream> #include <QTextStream>
@ -26,7 +26,7 @@ private slots:
private: private:
UAVObjectManager* objMngr; UAVObjectManager* objMngr;
TestObject1* obj1; ExampleObject* obj1;
QTimer* timer; QTimer* timer;
QTextStream sout; QTextStream sout;
bool done; bool done;

View File

@ -12,7 +12,6 @@ SOURCES += main.cpp \
../uavobject.cpp \ ../uavobject.cpp \
../uavmetaobject.cpp \ ../uavmetaobject.cpp \
../uavdataobject.cpp \ ../uavdataobject.cpp \
testobject1.cpp \
uavobjectstest.cpp \ uavobjectstest.cpp \
../exampleobject.cpp ../exampleobject.cpp
HEADERS += ../uavobjectmanager.h \ HEADERS += ../uavobjectmanager.h \
@ -20,6 +19,5 @@ HEADERS += ../uavobjectmanager.h \
../uavobject.h \ ../uavobject.h \
../uavmetaobject.h \ ../uavmetaobject.h \
../uavdataobject.h \ ../uavdataobject.h \
testobject1.h \
uavobjectstest.h \ uavobjectstest.h \
../exampleobject.h ../exampleobject.h

View File

@ -30,10 +30,11 @@
/** /**
* Constructor * Constructor
*/ */
UAVDataObject::UAVDataObject(quint32 objID, bool isSingleInst, const QString& name): UAVDataObject::UAVDataObject(quint32 objID, bool isSingleInst, bool isSet,const QString& name):
UAVObject(objID, isSingleInst, name) UAVObject(objID, isSingleInst, name)
{ {
mobj = NULL; mobj = NULL;
this->isSet = isSet;
} }
/** /**
@ -55,6 +56,14 @@ void UAVDataObject::initialize(UAVMetaObject* mobj)
this->mobj = mobj; this->mobj = mobj;
} }
/**
* Returns true if this is a data object holding module settings
*/
bool UAVDataObject::isSettings()
{
return isSet;
}
/** /**
* Set the object's metadata * Set the object's metadata
*/ */

View File

@ -39,9 +39,10 @@ class UAVOBJECTS_EXPORT UAVDataObject: public UAVObject
Q_OBJECT Q_OBJECT
public: public:
UAVDataObject(quint32 objID, bool isSingleInst, const QString& name); UAVDataObject(quint32 objID, bool isSingleInst, bool isSet, const QString& name);
void initialize(quint32 instID, UAVMetaObject* mobj); void initialize(quint32 instID, UAVMetaObject* mobj);
void initialize(UAVMetaObject* mobj); void initialize(UAVMetaObject* mobj);
bool isSettings();
void setMetadata(const Metadata& mdata); void setMetadata(const Metadata& mdata);
Metadata getMetadata(); Metadata getMetadata();
UAVMetaObject* getMetaObject(); UAVMetaObject* getMetaObject();
@ -49,6 +50,7 @@ public:
private: private:
UAVMetaObject* mobj; UAVMetaObject* mobj;
bool isSet;
}; };

View File

@ -26,6 +26,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "uavobject.h" #include "uavobject.h"
#include <QtEndian>
/** /**
* Constructor * Constructor
@ -242,6 +243,151 @@ qint32 UAVObject::unpack(const quint8* dataIn)
return numBytes; return numBytes;
} }
/**
* Save the object data to the file.
* The file will be created in the current directory
* and its name will be the same as the object with
* the .uavobj extension.
* @returns True on success, false on failure
*/
bool UAVObject::save()
{
QMutexLocker locker(mutex);
// Open file
QFile file(name + ".uavobj");
if (!file.open(QFile::WriteOnly))
{
return false;
}
// Write object
if ( !save(file) )
{
return false;
}
// Close file
file.close();
return true;
}
/**
* Save the object data to the file.
* The file is expected to be already open for writting.
* The data will be appended and the file will not be closed.
* @returns True on success, false on failure
*/
bool UAVObject::save(QFile& file)
{
QMutexLocker locker(mutex);
quint8 buffer[numBytes];
quint8 tmpId[4];
// Write the object ID
qToBigEndian<quint32>(objID, tmpId);
if ( file.write((const char*)tmpId, 4) == -1 )
{
return false;
}
// Write the instance ID
if (!isSingleInst)
{
qToBigEndian<quint16>(instID, tmpId);
if ( file.write((const char*)tmpId, 2) == -1 )
{
return false;
}
}
// Write the data
pack(buffer);
if ( file.write((const char*)buffer, numBytes) == -1 )
{
return false;
}
// Done
return true;
}
/**
* Load the object data from a file.
* The file will be openned in the current directory
* and its name will be the same as the object with
* the .uavobj extension.
* @returns True on success, false on failure
*/
bool UAVObject::load()
{
QMutexLocker locker(mutex);
// Open file
QFile file(name + ".uavobj");
if (!file.open(QFile::ReadOnly))
{
return false;
}
// Load object
if ( !load(file) )
{
return false;
}
// Close file
file.close();
return true;
}
/**
* Load the object data from file.
* The file is expected to be already open for reading.
* The data will be read and the file will not be closed.
* @returns True on success, false on failure
*/
bool UAVObject::load(QFile& file)
{
QMutexLocker locker(mutex);
quint8 buffer[numBytes];
quint8 tmpId[4];
// Read the object ID
if ( file.read((char*)tmpId, 4) != 4 )
{
return false;
}
// Check that the IDs match
if (qFromBigEndian<quint32>(tmpId) != objID)
{
return false;
}
// Read the instance ID
if ( file.read((char*)tmpId, 2) != 2 )
{
return false;
}
// Check that the IDs match
if (qFromBigEndian<quint16>(tmpId) != instID)
{
return false;
}
// Read and unpack the data
if ( file.read((char*)buffer, numBytes) != numBytes )
{
return false;
}
unpack(buffer);
// Done
return true;
}
/** /**
* Return a string with the object information * Return a string with the object information
*/ */

View File

@ -35,6 +35,7 @@
#include <QMutexLocker> #include <QMutexLocker>
#include <QString> #include <QString>
#include <QList> #include <QList>
#include <QFile>
#include "uavobjectfield.h" #include "uavobjectfield.h"
class UAVObjectField; class UAVObjectField;
@ -78,8 +79,12 @@ public:
bool isSingleInstance(); bool isSingleInstance();
QString getName(); QString getName();
quint32 getNumBytes(); quint32 getNumBytes();
virtual qint32 pack(quint8* dataOut); qint32 pack(quint8* dataOut);
virtual qint32 unpack(const quint8* dataIn); qint32 unpack(const quint8* dataIn);
bool save();
bool save(QFile& file);
bool load();
bool load(QFile& file);
virtual void setMetadata(const Metadata& mdata) = 0; virtual void setMetadata(const Metadata& mdata) = 0;
virtual Metadata getMetadata() = 0; virtual Metadata getMetadata() = 0;
virtual Metadata getDefaultMetadata() = 0; virtual Metadata getDefaultMetadata() = 0;

View File

@ -1,9 +1,7 @@
TEMPLATE = lib TEMPLATE = lib
TARGET = UAVObjects TARGET = UAVObjects
include(../../openpilotgcsplugin.pri) include(../../openpilotgcsplugin.pri)
include(uavobjects_dependencies.pri) include(uavobjects_dependencies.pri)
HEADERS += uavobjects_global.h \ HEADERS += uavobjects_global.h \
uavobject.h \ uavobject.h \
uavmetaobject.h \ uavmetaobject.h \
@ -11,15 +9,17 @@ HEADERS += uavobjects_global.h \
uavdataobject.h \ uavdataobject.h \
uavobjectfield.h \ uavobjectfield.h \
uavobjectsinit.h \ uavobjectsinit.h \
uavobjectsplugin.h uavobjectsplugin.h \
examplesettings.h \
exampleobject.h
SOURCES += uavobject.cpp \ SOURCES += uavobject.cpp \
uavmetaobject.cpp \ uavmetaobject.cpp \
uavobjectmanager.cpp \ uavobjectmanager.cpp \
uavdataobject.cpp \ uavdataobject.cpp \
uavobjectfield.cpp \ uavobjectfield.cpp \
uavobjectsinit.cpp \ uavobjectsinit.cpp \
uavobjectsplugin.cpp uavobjectsplugin.cpp \
examplesettings.cpp \
exampleobject.cpp
DEFINES += UAVOBJECTS_LIBRARY DEFINES += UAVOBJECTS_LIBRARY
OTHER_FILES += UAVObjects.pluginspec OTHER_FILES += UAVObjects.pluginspec

View File

@ -31,6 +31,7 @@
*/ */
#include "uavobjectsinit.h" #include "uavobjectsinit.h"
#include "exampleobject.h" #include "exampleobject.h"
#include "examplesettings.h"
/** /**
@ -40,4 +41,6 @@
void UAVObjectsInitialize(UAVObjectManager* objMngr) void UAVObjectsInitialize(UAVObjectManager* objMngr)
{ {
objMngr->registerObject( new ExampleObject() ); objMngr->registerObject( new ExampleObject() );
objMngr->registerObject( new ExampleSettings() );
} }

View File

@ -32,7 +32,7 @@
const QString $(NAME)::NAME = QString("$(NAME)"); const QString $(NAME)::NAME = QString("$(NAME)");
$(NAME)::$(NAME)(): UAVDataObject(OBJID, SINGLEINST, NAME) $(NAME)::$(NAME)(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
{ {
// Create fields // Create fields
QList<UAVObjectField*> fields; QList<UAVObjectField*> fields;

View File

@ -42,7 +42,8 @@ $(DATAFIELDS)
static const quint32 OBJID = $(OBJID)U; static const quint32 OBJID = $(OBJID)U;
static const QString NAME; static const QString NAME;
static const bool SINGLEINST = $(SINGLEINST); static const bool ISSINGLEINST = $(ISSINGLEINST);
static const bool ISSETTINGS = $(ISSETTINGS);
static const quint32 NUMBYTES = sizeof(DataFields); static const quint32 NUMBYTES = sizeof(DataFields);
$(NAME)(); $(NAME)();

View File

@ -160,7 +160,7 @@ bool UAVTalk::processInputByte(quint8 rxbyte)
if (rxCount == 4) if (rxCount == 4)
{ {
// Search for object, if not found reset state machine // Search for object, if not found reset state machine
rxObjId = (qint32)qFromBigEndian<qint32>(rxTmpBuffer); rxObjId = (qint32)qFromBigEndian<quint32>(rxTmpBuffer);
UAVObject* rxObj = objMngr->getObject(rxObjId); UAVObject* rxObj = objMngr->getObject(rxObjId);
if (rxObj == NULL) if (rxObj == NULL)
{ {
@ -214,7 +214,7 @@ bool UAVTalk::processInputByte(quint8 rxbyte)
rxTmpBuffer[rxCount++] = rxbyte; rxTmpBuffer[rxCount++] = rxbyte;
if (rxCount == 2) if (rxCount == 2)
{ {
rxInstId = (qint16)qFromBigEndian<qint16>(rxTmpBuffer); rxInstId = (qint16)qFromBigEndian<quint16>(rxTmpBuffer);
rxCS = updateChecksum(rxCS, rxTmpBuffer, 2); rxCS = updateChecksum(rxCS, rxTmpBuffer, 2);
rxCount = 0; rxCount = 0;
// If there is a payload get it, otherwise receive checksum // If there is a payload get it, otherwise receive checksum
@ -241,7 +241,7 @@ bool UAVTalk::processInputByte(quint8 rxbyte)
rxTmpBuffer[rxCount++] = rxbyte; rxTmpBuffer[rxCount++] = rxbyte;
if (rxCount == 2) if (rxCount == 2)
{ {
rxCSPacket = (qint16)qFromBigEndian<qint16>(rxTmpBuffer); rxCSPacket = (qint16)qFromBigEndian<quint16>(rxTmpBuffer);
if (rxCS == rxCSPacket) if (rxCS == rxCSPacket)
{ {
mutex->lock(); mutex->lock();
@ -491,7 +491,7 @@ bool UAVTalk::transmitSingleObject(UAVObject* obj, quint8 type, bool allInstance
// Setup type and object id fields // Setup type and object id fields
objId = obj->getObjID(); objId = obj->getObjID();
txBuffer[0] = type; txBuffer[0] = type;
qToBigEndian<qint32>(objId, &txBuffer[1]); qToBigEndian<quint32>(objId, &txBuffer[1]);
// Setup instance ID if one is required // Setup instance ID if one is required
if ( obj->isSingleInstance() ) if ( obj->isSingleInstance() )
@ -503,12 +503,12 @@ bool UAVTalk::transmitSingleObject(UAVObject* obj, quint8 type, bool allInstance
// Check if all instances are requested // Check if all instances are requested
if (allInstances) if (allInstances)
{ {
qToBigEndian<qint16>(allInstId, &txBuffer[5]); qToBigEndian<quint16>(allInstId, &txBuffer[5]);
} }
else else
{ {
instId = obj->getInstID(); instId = obj->getInstID();
qToBigEndian<qint16>(instId, &txBuffer[5]); qToBigEndian<quint16>(instId, &txBuffer[5]);
} }
dataOffset = 7; dataOffset = 7;
} }
@ -541,7 +541,7 @@ bool UAVTalk::transmitSingleObject(UAVObject* obj, quint8 type, bool allInstance
// Calculate checksum // Calculate checksum
cs = 0; cs = 0;
cs = updateChecksum(cs, txBuffer, dataOffset+length); cs = updateChecksum(cs, txBuffer, dataOffset+length);
qToBigEndian<qint16>(cs, &txBuffer[dataOffset+length]); qToBigEndian<quint16>(cs, &txBuffer[dataOffset+length]);
// Send buffer // Send buffer
io->write((const char*)txBuffer, dataOffset+length+CHECKSUM_LENGTH); io->write((const char*)txBuffer, dataOffset+length+CHECKSUM_LENGTH);