diff --git a/ground/src/plugins/uavobjects/tests/main.cpp b/ground/src/plugins/uavobjects/tests/main.cpp new file mode 100644 index 000000000..8410e63e0 --- /dev/null +++ b/ground/src/plugins/uavobjects/tests/main.cpp @@ -0,0 +1,12 @@ +#include +#include +#include "uavobjectstest.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + UAVObjectsTest* test = new UAVObjectsTest(); + + return a.exec(); +} diff --git a/ground/src/plugins/uavobjects/tests/testobject1.cpp b/ground/src/plugins/uavobjects/tests/testobject1.cpp new file mode 100644 index 000000000..03538ca28 --- /dev/null +++ b/ground/src/plugins/uavobjects/tests/testobject1.cpp @@ -0,0 +1,51 @@ +#include "testobject1.h" + +const QString TestObject1::NAME = QString("TestObject1"); + +TestObject1::TestObject1(): UAVDataObject(OBJID, SINGLEINST, NAME) +{ + // Create fields + QList fields; + fields.append(new UAVObjectField(QString("Field1"), QString("unit1"), UAVObjectField::FIELDTYPE_INT16, 1)); + fields.append(new UAVObjectField(QString("Field2"), QString("unit2"), UAVObjectField::FIELDTYPE_FLOAT32, 3)); + fields.append(new UAVObjectField(QString("Field3"), QString("unit3"), UAVObjectField::FIELDTYPE_INT8, 1)); + fields.append(new UAVObjectField(QString("Field4"), QString("unit4"), UAVObjectField::FIELDTYPE_INT32, 1)); + + // Initialize object + initializeFields(fields, (quint8*)&data, NUMBYTES); +} + +UAVObject::Metadata TestObject1::getDefaultMetadata() +{ + // Create metadata + UAVObject::Metadata metadata; + metadata.ackRequired = true; + metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC; + metadata.gcsTelemetryUpdatePeriod = 200; + metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_NEVER; + metadata.flightTelemetryUpdatePeriod = 0; + metadata.loggingUpdateMode = UAVObject::UPDATEMODE_NEVER; + metadata.loggingUpdatePeriod = 0; + return metadata; +} + +TestObject1::DataFields TestObject1::getData() +{ + QMutexLocker locker(mutex); + return data; +} + +void TestObject1::setData(DataFields& data) +{ + QMutexLocker locker(mutex); + this->data = data; + emit objectUpdatedAuto(this); // trigger object updated event + emit objectUpdated(this); +} + +UAVDataObject* TestObject1::clone(quint32 instID) +{ + TestObject1* obj = new TestObject1(); + obj->initialize(instID, this->getMetaObject()); + return obj; +} diff --git a/ground/src/plugins/uavobjects/tests/testobject1.h b/ground/src/plugins/uavobjects/tests/testobject1.h new file mode 100644 index 000000000..57ace76c1 --- /dev/null +++ b/ground/src/plugins/uavobjects/tests/testobject1.h @@ -0,0 +1,33 @@ +#ifndef TESTOBJECT1_H +#define TESTOBJECT1_H + +#include "..\uavdataobject.h" + +class TestObject1: public UAVDataObject +{ +public: + typedef struct { + qint16 field1; + float field2[3]; + qint8 field3; + qint32 field4; + } __attribute__((packed)) DataFields; + + static const quint32 OBJID = 0x0005; + static const QString NAME; + static const bool SINGLEINST = false; + static const quint32 NUMBYTES = sizeof(DataFields); + + TestObject1(); + + DataFields getData(); + void setData(DataFields& data); + Metadata getDefaultMetadata(); + UAVDataObject* clone(quint32 instID); + +private: + DataFields data; + +}; + +#endif // TESTOBJECT1_H diff --git a/ground/src/plugins/uavobjects/tests/uavobjectstest.cpp b/ground/src/plugins/uavobjects/tests/uavobjectstest.cpp new file mode 100644 index 000000000..4debce668 --- /dev/null +++ b/ground/src/plugins/uavobjects/tests/uavobjectstest.cpp @@ -0,0 +1,116 @@ +#include "uavobjectstest.h" + +UAVObjectsTest::UAVObjectsTest(): sout(stdout), done(false) +{ + // Create object manager + objMngr = new UAVObjectManager(); + connect(objMngr, SIGNAL(newObject(UAVObject*)), this, SLOT(newObject(UAVObject*))); + connect(objMngr, SIGNAL(newInstance(UAVObject*)), this, SLOT(newInstance(UAVObject*))); + + // Create test objects + obj1 = new TestObject1(); + connect(obj1, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(objectUpdated(UAVObject*))); + connect(obj1, SIGNAL(objectUpdatedAuto(UAVObject*)), this, SLOT(objectUpdatedAuto(UAVObject*))); + connect(obj1, SIGNAL(objectUpdatedManual(UAVObject*)), this, SLOT(objectUpdatedManual(UAVObject*))); + connect(obj1, SIGNAL(objectUnpacked(UAVObject*)), this, SLOT(objectUnpacked(UAVObject*))); + connect(obj1, SIGNAL(updateRequested(UAVObject*)), this, SLOT(updateRequested(UAVObject*))); + objMngr->registerObject(obj1); + + // Setup timer + timer = new QTimer(); + connect(timer, SIGNAL(timeout()), this, SLOT(runTest())); + timer->start(1000); +} + +void UAVObjectsTest::objectUpdated(UAVObject* obj) +{ + sout << QString("[Object Updated]\n%1").arg(obj->toString()); +} + +void UAVObjectsTest::objectUpdatedAuto(UAVObject* obj) +{ + sout << QString("[Object Updated AUTO]\n%1").arg(obj->toString()); +} + +void UAVObjectsTest::objectUpdatedManual(UAVObject* obj) +{ + sout << QString("[Object Updated MANUAL]\n%1").arg(obj->toString()); +} + +void UAVObjectsTest::objectUnpacked(UAVObject* obj) +{ + sout << QString("[Object Updated UNPACKED]\n%1").arg(obj->toString()); +} + +void UAVObjectsTest::updateRequested(UAVObject* obj) +{ + sout << QString("[Object Update Requested]\n%1").arg(obj->toString()); +} + +void UAVObjectsTest::newObject(UAVObject* obj) +{ + sout << QString("[New object]\n%1").arg(obj->toString()); +} + +void UAVObjectsTest::newInstance(UAVObject* obj) +{ + sout << QString("[New instance]\n%1").arg(obj->toString()); +} + +void UAVObjectsTest::runTest() +{ + if (!done) + { + // Create a new instance + TestObject1* obj2 = new TestObject1(); + objMngr->registerObject(obj2); + + // Set data + TestObject1::DataFields data = obj1->getData(); + data.field1 = 1; + data.field2[0] = 2.1; + data.field2[1] = 2.2; + data.field2[2] = 2.3; + data.field3 = 3; + data.field4 = 4; + obj1->setData(data); + + // Set metadata + UAVObject::Metadata mdata = obj1->getMetadata(); + mdata.gcsTelemetryUpdatePeriod = 123; + obj1->setMetadata(mdata); + // Print metadata of both instances + sout << "[Meta of obj1]\n"; + sout << obj1->getMetaObject()->toString(); + sout << "[Meta of obj2]\n"; + sout << obj2->getMetaObject()->toString(); + + // Create a new instance using clone() and an out of order instance ID + UAVDataObject* obj3 = obj2->clone(5); + objMngr->registerObject(obj3); + + // Pack, unpack testing + quint8* buf = new quint8[obj1->getNumBytes()]; + obj1->pack(buf); + data.field1 = 10; + data.field2[0] = 20.1; + data.field2[1] = 20.2; + data.field2[2] = 20.3; + data.field3 = 30; + data.field4 = 40; + obj1->setData(data); + obj1->unpack(buf); + + // Get all instances + QList objs = objMngr->getObjectInstances(TestObject1::OBJID); + for (int n = 0; n < objs.length(); ++n) + { + sout << "[Printing object instances]\n"; + sout << objs[n]->toString(); + } + + // Done + done = true; + } + sout.flush(); +} diff --git a/ground/src/plugins/uavobjects/tests/uavobjectstest.h b/ground/src/plugins/uavobjects/tests/uavobjectstest.h new file mode 100644 index 000000000..a4a6ab6b9 --- /dev/null +++ b/ground/src/plugins/uavobjects/tests/uavobjectstest.h @@ -0,0 +1,35 @@ +#ifndef UAVOBJECTSTEST_H +#define UAVOBJECTSTEST_H + +#include "..\UAVObjectManager.h" +#include "testobject1.h" +#include +#include + +class UAVObjectsTest: QObject +{ + Q_OBJECT + + +public: + UAVObjectsTest(); + +private slots: + void objectUpdated(UAVObject* obj); + void objectUpdatedAuto(UAVObject* obj); + void objectUpdatedManual(UAVObject* obj); + void objectUnpacked(UAVObject* obj); + void updateRequested(UAVObject* obj); + void runTest(); + void newObject(UAVObject* obj); + void newInstance(UAVObject* obj); + +private: + UAVObjectManager* objMngr; + TestObject1* obj1; + QTimer* timer; + QTextStream sout; + bool done; +}; + +#endif // UAVOBJECTSTEST_H diff --git a/ground/src/plugins/uavobjects/tests/uavobjectstest.pro b/ground/src/plugins/uavobjects/tests/uavobjectstest.pro new file mode 100644 index 000000000..ac29be11b --- /dev/null +++ b/ground/src/plugins/uavobjects/tests/uavobjectstest.pro @@ -0,0 +1,23 @@ +# ------------------------------------------------- +# Project created by QtCreator 2010-03-13T15:17:38 +# ------------------------------------------------- +QT -= gui +TARGET = uavobjectstest +CONFIG += console +CONFIG -= app_bundle +TEMPLATE = app +SOURCES += main.cpp \ + ../uavobjectmanager.cpp \ + ../uavobjectfield.cpp \ + ../uavobject.cpp \ + ../uavmetaobject.cpp \ + ../uavdataobject.cpp \ + testobject1.cpp \ + uavobjectstest.cpp +HEADERS += ../uavobjectmanager.h \ + ../uavobjectfield.h \ + ../uavobject.h \ + ../uavmetaobject.h \ + ../uavdataobject.h \ + testobject1.h \ + uavobjectstest.h diff --git a/ground/src/plugins/uavobjects/uavdataobject.cpp b/ground/src/plugins/uavobjects/uavdataobject.cpp index 3ece1de94..e170bb9be 100644 --- a/ground/src/plugins/uavobjects/uavdataobject.cpp +++ b/ground/src/plugins/uavobjects/uavdataobject.cpp @@ -25,90 +25,67 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "uavdataobject.h" - -UAVDataObject::UAVDataObject(quint32 objID, quint32 instID, bool isSingleInst, QString& name, quint32 numBytes): - UAVObject(objID, instID, isSingleInst, name, numBytes) -{ - data = new quint8[numBytes]; // create data buffer, object fields are stored there as a packed structure - mobj = NULL; -} - -void UAVDataObject::initialize(QList fields, Metadata& mdata) -{ - UAVMetaObject* obj = new UAVMetaObject(objID+1, name.append("Meta"), mdata, this); - initialize(fields, obj); -} - -void UAVDataObject::initialize(QList fields, UAVMetaObject* mobj) -{ - // Initialize fields and create data buffer - this->mobj = mobj; - this->fields = fields; - quint32 offset = 0; - for (int n = 0; n < fields.length(); ++n) - { - fields.value(n)->initialize(data, offset, this); - offset += fields.value(n)->getNumBytes(); - connect(fields.value(n), SIGNAL(fieldUpdated(UAVObjectField*)), this, SLOT(fieldUpdated(UAVObjectField*))); - } -} - -void UAVDataObject::fieldUpdated(UAVObjectField* field) -{ - emit objectUpdated(this, false); // trigger object updated event -} - -qint32 UAVDataObject::getNumFields() -{ - return fields.count(); -} - -QList UAVDataObject::getFields() -{ - return fields; -} - -UAVObjectField* UAVDataObject::getField(QString& name) -{ - // Look for field - for (int n = 0; n < fields.length(); ++n) - { - if (name.compare(fields.value(n)->getName()) == 0) - { - return fields.value(n); - } - } - // If this point is reached then the field was not found - return NULL; -} - -qint32 UAVDataObject::pack(quint8* dataOut) -{ - QMutexLocker locker(mutex); - memcpy(dataOut, data, numBytes); - return numBytes; -} - -qint32 UAVDataObject::unpack(const quint8* dataIn) -{ - QMutexLocker locker(mutex); - memcpy(data, dataIn, numBytes); - emit objectUpdated(this, true); // trigger object updated event - return numBytes; -} - -void UAVDataObject::setMetadata(const Metadata& mdata) -{ - mobj->setData(mdata); -} - -UAVObject::Metadata UAVDataObject::getMetadata(void) -{ - return mobj->getData(); -} - -UAVMetaObject* UAVDataObject::getMetaObject() -{ - return mobj; -} +#include "uavdataobject.h" + +/** + * Constructor + */ +UAVDataObject::UAVDataObject(quint32 objID, bool isSingleInst, const QString& name): + UAVObject(objID, isSingleInst, name) +{ + mobj = NULL; +} + +/** + * Initialize instance ID and assign a metaobject + */ +void UAVDataObject::initialize(quint32 instID, UAVMetaObject* mobj) +{ + QMutexLocker locker(mutex); + this->mobj = mobj; + UAVObject::initialize(instID); +} + +/** + * Assign a metaobject + */ +void UAVDataObject::initialize(UAVMetaObject* mobj) +{ + QMutexLocker locker(mutex); + this->mobj = mobj; +} + +/** + * Set the object's metadata + */ +void UAVDataObject::setMetadata(const Metadata& mdata) +{ + if ( mobj!=NULL ) + { + mobj->setData(mdata); + } +} + +/** + * Get the object's metadata + */ +UAVObject::Metadata UAVDataObject::getMetadata(void) +{ + if ( mobj!=NULL) + { + return mobj->getData(); + } + else + { + return getDefaultMetadata(); + } +} + +/** + * Get the metaobject + */ +UAVMetaObject* UAVDataObject::getMetaObject() +{ + return mobj; +} + diff --git a/ground/src/plugins/uavobjects/uavdataobject.h b/ground/src/plugins/uavobjects/uavdataobject.h index c8d43a726..42ccf83eb 100644 --- a/ground/src/plugins/uavobjects/uavdataobject.h +++ b/ground/src/plugins/uavobjects/uavdataobject.h @@ -25,43 +25,30 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef UAVDATAOBJECT_H -#define UAVDATAOBJECT_H - -#include "uavobject.h" -#include "uavobjectfield.h" -#include "uavmetaobject.h" -#include - -class UAVDataObject: public UAVObject -{ - Q_OBJECT - -public: - UAVDataObject(quint32 objID, quint32 instID, bool isSingleInst, QString& name, quint32 numBytes); - void initialize(QList fields, Metadata& mdata); - void initialize(QList fields, UAVMetaObject* mobj); - - qint32 getNumFields(); - QList getFields(); - UAVObjectField* getField(QString& name); - qint32 pack(quint8* dataOut); - qint32 unpack(const quint8* dataIn); - void setMetadata(const Metadata& mdata); - Metadata getMetadata(); - UAVMetaObject* getMetaObject(); - -private slots: - void fieldUpdated(UAVObjectField* field); - -private: - quint8* data; - QList fields; - UAVMetaObject* mobj; - - void initialize(QList fields); - - -}; - -#endif // UAVDATAOBJECT_H +#ifndef UAVDATAOBJECT_H +#define UAVDATAOBJECT_H + +#include "uavobject.h" +#include "uavobjectfield.h" +#include "uavmetaobject.h" +#include + +class UAVDataObject: public UAVObject +{ + Q_OBJECT + +public: + UAVDataObject(quint32 objID, bool isSingleInst, const QString& name); + void initialize(quint32 instID, UAVMetaObject* mobj); + void initialize(UAVMetaObject* mobj); + void setMetadata(const Metadata& mdata); + Metadata getMetadata(); + UAVMetaObject* getMetaObject(); + virtual UAVDataObject* clone(quint32 instID = 0) = 0; + +private: + UAVMetaObject* mobj; + +}; + +#endif // UAVDATAOBJECT_H diff --git a/ground/src/plugins/uavobjects/uavmetaobject.cpp b/ground/src/plugins/uavobjects/uavmetaobject.cpp index b131e349a..f9e9ee5ef 100644 --- a/ground/src/plugins/uavobjects/uavmetaobject.cpp +++ b/ground/src/plugins/uavobjects/uavmetaobject.cpp @@ -25,61 +25,90 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "uavmetaobject.h" - -UAVMetaObject::UAVMetaObject(quint32 objID, QString& name, Metadata& mdata, UAVObject* parent): - UAVObject(objID, 0, true, name, sizeof(Metadata)) -{ - this->parentMetadata = mdata; - this->parent = parent; - ownMetadata.ackRequired = 1; - ownMetadata.flightTelemetryUpdateMode = UPDATEMODE_ONCHANGE; - ownMetadata.flightTelemetryUpdatePeriod = 0; - ownMetadata.gcsTelemetryUpdateMode = UPDATEMODE_ONCHANGE; - ownMetadata.gcsTelemetryUpdatePeriod = 0; - ownMetadata.loggingUpdateMode = UPDATEMODE_ONCHANGE; - ownMetadata.loggingUpdatePeriod = 0; -} - -UAVObject* UAVMetaObject::getParentObject() -{ - return parent; -} - -qint32 UAVMetaObject::pack(quint8* dataOut) -{ - QMutexLocker locker(mutex); - memcpy(dataOut, &parentMetadata, sizeof(Metadata)); - return sizeof(Metadata); -} - -qint32 UAVMetaObject::unpack(const quint8* dataIn) -{ - QMutexLocker locker(mutex); - memcpy(&parentMetadata, dataIn, sizeof(Metadata)); - emit objectUpdated(this, true); // trigger object updated event - return sizeof(Metadata); -} - -void UAVMetaObject::setMetadata(const Metadata& mdata) -{ - return; // can not update metaobject's metadata -} - -UAVObject::Metadata UAVMetaObject::getMetadata() -{ - return ownMetadata; -} - -void UAVMetaObject::setData(const Metadata& mdata) -{ - QMutexLocker locker(mutex); - parentMetadata = mdata; - emit objectUpdated(this, false); // trigger object updated event -} - -UAVObject::Metadata UAVMetaObject::getData() -{ - QMutexLocker locker(mutex); - return parentMetadata; -} +#include "uavmetaobject.h" + +/** + * Constructor + */ +UAVMetaObject::UAVMetaObject(quint32 objID, const QString& name, UAVObject* parent): + UAVObject(objID, true, name) +{ + this->parent = parent; + // Setup default metadata of metaobject (can not be changed) + ownMetadata.ackRequired = 1; + ownMetadata.flightTelemetryUpdateMode = UPDATEMODE_ONCHANGE; + ownMetadata.flightTelemetryUpdatePeriod = 0; + ownMetadata.gcsTelemetryUpdateMode = UPDATEMODE_ONCHANGE; + ownMetadata.gcsTelemetryUpdatePeriod = 0; + ownMetadata.loggingUpdateMode = UPDATEMODE_ONCHANGE; + ownMetadata.loggingUpdatePeriod = 0; + // Setup fields + QList fields; + fields.append(new UAVObjectField(QString("AckRequired"), QString(""), UAVObjectField::FIELDTYPE_INT8, 1)); + fields.append(new UAVObjectField(QString("FlightTelemetryUpdateMode"), QString(""), UAVObjectField::FIELDTYPE_INT8, 1)); + fields.append(new UAVObjectField(QString("FlightTelemetryUpdatePeriod"), QString("ms"), UAVObjectField::FIELDTYPE_INT32, 1)); + fields.append(new UAVObjectField(QString("GCSTelemetryUpdateMode"), QString(""), UAVObjectField::FIELDTYPE_INT8, 1)); + fields.append(new UAVObjectField(QString("GCSTelemetryUpdatePeriod"), QString("ms"), UAVObjectField::FIELDTYPE_INT32, 1)); + fields.append(new UAVObjectField(QString("LoggingUpdateMode"), QString(""), UAVObjectField::FIELDTYPE_INT8, 1)); + fields.append(new UAVObjectField(QString("LoggingUpdatePeriod"), QString("ms"), UAVObjectField::FIELDTYPE_INT32, 1)); + // Initialize parent + UAVObject::initialize(0); + UAVObject::initializeFields(fields, (quint8*)&parentMetadata, sizeof(Metadata)); + // Setup metadata of parent + parentMetadata = parent->getDefaultMetadata(); +} + +/** + * Get the parent object + */ +UAVObject* UAVMetaObject::getParentObject() +{ + return parent; +} + +/** + * Set the metadata of the metaobject, this function will + * do nothing since metaobjects have read-only metadata. + */ +void UAVMetaObject::setMetadata(const Metadata& mdata) +{ + return; // can not update metaobject's metadata +} + +/** + * Get the metadata of the metaobject + */ +UAVObject::Metadata UAVMetaObject::getMetadata() +{ + return ownMetadata; +} + +/** + * Get the default metadata + */ +UAVObject::Metadata UAVMetaObject::getDefaultMetadata() +{ + return ownMetadata; +} + +/** + * Set the metadata held by the metaobject + */ +void UAVMetaObject::setData(const Metadata& mdata) +{ + QMutexLocker locker(mutex); + parentMetadata = mdata; + emit objectUpdatedAuto(this); // trigger object updated event + emit objectUpdated(this); +} + +/** + * Get the metadata held by the metaobject + */ +UAVObject::Metadata UAVMetaObject::getData() +{ + QMutexLocker locker(mutex); + return parentMetadata; +} + + diff --git a/ground/src/plugins/uavobjects/uavmetaobject.h b/ground/src/plugins/uavobjects/uavmetaobject.h index 7d3e083c6..31b49a7dd 100644 --- a/ground/src/plugins/uavobjects/uavmetaobject.h +++ b/ground/src/plugins/uavobjects/uavmetaobject.h @@ -25,31 +25,29 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef UAVMETAOBJECT_H -#define UAVMETAOBJECT_H - -#include "uavobject.h" - -class UAVMetaObject: public UAVObject -{ - Q_OBJECT - -public: - UAVMetaObject(quint32 objID, QString& name, Metadata& mdata, UAVObject* parent); - UAVObject* getParentObject(); - - qint32 pack(quint8* dataOut); - qint32 unpack(const quint8* dataIn); - void setMetadata(const Metadata& mdata); - Metadata getMetadata(); - void setData(const Metadata& mdata); - Metadata getData(); - -private: - UAVObject* parent; - Metadata ownMetadata; - Metadata parentMetadata; - -}; - -#endif // UAVMETAOBJECT_H +#ifndef UAVMETAOBJECT_H +#define UAVMETAOBJECT_H + +#include "uavobject.h" + +class UAVMetaObject: public UAVObject +{ + Q_OBJECT + +public: + UAVMetaObject(quint32 objID, const QString& name, UAVObject* parent); + UAVObject* getParentObject(); + void setMetadata(const Metadata& mdata); + Metadata getMetadata(); + Metadata getDefaultMetadata(); + void setData(const Metadata& mdata); + Metadata getData(); + +private: + UAVObject* parent; + Metadata ownMetadata; + Metadata parentMetadata; + +}; + +#endif // UAVMETAOBJECT_H diff --git a/ground/src/plugins/uavobjects/uavobject.cpp b/ground/src/plugins/uavobjects/uavobject.cpp index d4ce187fe..8a5e57376 100644 --- a/ground/src/plugins/uavobjects/uavobject.cpp +++ b/ground/src/plugins/uavobjects/uavobject.cpp @@ -25,71 +25,259 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "uavobject.h" - - -UAVObject::UAVObject(quint32 objID, quint32 instID, bool isSingleInst, QString& name, quint32 numBytes): QObject() -{ - this->objID = objID; - this->instID = instID; - this->isSingleInst = isSingleInst; - this->name = name; - this->numBytes = numBytes; - this->mutex = new QMutex(QMutex::Recursive); -} - -quint32 UAVObject::getObjID() -{ - return objID; -} - -quint32 UAVObject::getInstID() -{ - return instID; -} - -bool UAVObject::isSingleInstance() -{ - return isSingleInst; -} - -QString UAVObject::getName() -{ - return name; -} - -quint32 UAVObject::getNumBytes() -{ - return numBytes; -} - -void UAVObject::requestUpdate() -{ - emit updateRequested(this); -} - -void UAVObject::updated() -{ - emit objectUpdated(this, false); -} - -void UAVObject::lock() -{ - mutex->lock(); -} - -void UAVObject::lock(int timeoutMs) -{ - mutex->tryLock(timeoutMs); -} - -void UAVObject::unlock() -{ - mutex->unlock(); -} - -QMutex* UAVObject::getMutex() -{ - return mutex; -} - +#include "uavobject.h" + +/** + * Constructor + * @param objID The object ID + * @param isSingleInst True if this object can only have a single instance + * @param name Object name + */ +UAVObject::UAVObject(quint32 objID, bool isSingleInst, const QString& name) +{ + this->objID = objID; + this->instID = 0; + this->isSingleInst = isSingleInst; + this->name = name; + this->mutex = new QMutex(QMutex::Recursive); +} + +/** + * Initialize object with its instance ID + */ +void UAVObject::initialize(quint32 instID) +{ + QMutexLocker locker(mutex); + this->instID = instID; +} + +/** + * Initialize objects' data fields + * @param fields List of fields held by the object + * @param data Pointer to that actual object data, this is needed by the fields to access the data + * @param numBytes Number of bytes in the object (total, including all fields) + */ +void UAVObject::initializeFields(QList& fields, quint8* data, quint32 numBytes) +{ + QMutexLocker locker(mutex); + this->numBytes = numBytes; + this->data = data; + this->fields = fields; + // Initialize fields + quint32 offset = 0; + for (int n = 0; n < fields.length(); ++n) + { + fields[n]->initialize(data, offset, this); + offset += fields[n]->getNumBytes(); + connect(fields[n], SIGNAL(fieldUpdated(UAVObjectField*)), this, SLOT(fieldUpdated(UAVObjectField*))); + } +} + +/** + * Called from the fields each time they are updated + */ +void UAVObject::fieldUpdated(UAVObjectField* field) +{ + emit objectUpdatedAuto(this); // trigger object updated event + emit objectUpdated(this); +} + +/** + * Get the object ID + */ +quint32 UAVObject::getObjID() +{ + return objID; +} + +/** + * Get the instance ID + */ +quint32 UAVObject::getInstID() +{ + return instID; +} + +/** + * Returns true if this is a single instance object + */ +bool UAVObject::isSingleInstance() +{ + return isSingleInst; +} + +/** + * Get the name of the object + */ +QString UAVObject::getName() +{ + return name; +} + +/** + * Get the total number of bytes of the object's data + */ +quint32 UAVObject::getNumBytes() +{ + return numBytes; +} + +/** + * Request that this object is updated with the latest values from the autopilot + */ +void UAVObject::requestUpdate() +{ + emit updateRequested(this); +} + +/** + * Signal that the object has been updated + */ +void UAVObject::updated() +{ + emit objectUpdatedManual(this); + emit objectUpdated(this); +} + +/** + * Lock mutex of this object + */ +void UAVObject::lock() +{ + mutex->lock(); +} + +/** + * Lock mutex of this object + */ +void UAVObject::lock(int timeoutMs) +{ + mutex->tryLock(timeoutMs); +} + +/** + * Unlock mutex of this object + */ +void UAVObject::unlock() +{ + mutex->unlock(); +} + +/** + * Get object's mutex + */ +QMutex* UAVObject::getMutex() +{ + return mutex; +} + +/** + * Get the number of fields held by this object + */ +qint32 UAVObject::getNumFields() +{ + QMutexLocker locker(mutex); + return fields.count(); +} + +/** + * Get the object's fields + */ +QList UAVObject::getFields() +{ + QMutexLocker locker(mutex); + return fields; +} + +/** + * Get a specific field + * @returns The field or NULL if not found + */ +UAVObjectField* UAVObject::getField(QString& name) +{ + QMutexLocker locker(mutex); + // Look for field + for (int n = 0; n < fields.length(); ++n) + { + if (name.compare(fields[n]->getName()) == 0) + { + return fields[n]; + } + } + // If this point is reached then the field was not found + return NULL; +} + +/** + * Pack the object data into a byte array + * @returns The number of bytes copied + */ +qint32 UAVObject::pack(quint8* dataOut) +{ + QMutexLocker locker(mutex); + qint32 offset = 0; + for (int n = 0; n < fields.length(); ++n) + { + fields[n]->pack(&dataOut[offset]); + offset += fields[n]->getNumBytes(); + } + return numBytes; +} + +/** + * Unpack the object data from a byte array + * @returns The number of bytes copied + */ +qint32 UAVObject::unpack(const quint8* dataIn) +{ + QMutexLocker locker(mutex); + qint32 offset = 0; + for (int n = 0; n < fields.length(); ++n) + { + fields[n]->unpack(&dataIn[offset]); + offset += fields[n]->getNumBytes(); + } + emit objectUnpacked(this); // trigger object updated event + emit objectUpdated(this); + return numBytes; +} + +/** + * Return a string with the object information + */ +QString UAVObject::toString() +{ + QString sout; + sout.append( toStringBrief() ); + sout.append( toStringData() ); + return sout; +} + +/** + * Return a string with the object information (only the header) + */ +QString UAVObject::toStringBrief() +{ + QString sout; + sout.append( QString("%1 (ID: %2, InstID: %3, NumBytes: %4, SInst: %5)\n") + .arg(getName()) + .arg(getObjID()) + .arg(getInstID()) + .arg(getNumBytes()) + .arg(isSingleInstance()) ); + return sout; +} + +/** + * Return a string with the object information (only the data) + */ +QString UAVObject::toStringData() +{ + QString sout; + sout.append("Data:\n"); + for (int n = 0; n < fields.length(); ++n) + { + sout.append( QString("\t%1").arg(fields[n]->toString()) ); + } + return sout; +} diff --git a/ground/src/plugins/uavobjects/uavobject.h b/ground/src/plugins/uavobjects/uavobject.h index 6a3c76327..4f7954977 100644 --- a/ground/src/plugins/uavobjects/uavobject.h +++ b/ground/src/plugins/uavobjects/uavobject.h @@ -25,75 +25,96 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef UAVOBJECT_H -#define UAVOBJECT_H - -#include -#include -#include -#include -#include - -class UAVObject: public QObject -{ - Q_OBJECT - -public: - - /** - * Object update mode - */ - typedef enum { - UPDATEMODE_PERIODIC = 0, /** Automatically update object at periodic intervals */ - UPDATEMODE_ONCHANGE, /** Only update object when its data changes */ - UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */ - UPDATEMODE_NEVER /** Object is never updated */ - } UpdateMode; - - /** - * Object metadata, each object has a meta object that holds its metadata. The metadata define - * properties for each object and can be used by multiple modules (e.g. telemetry and logger) - */ - typedef struct { - quint8 ackRequired; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ - UpdateMode flightTelemetryUpdateMode; /** Update mode used by the autopilot */ - qint32 flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */ - UpdateMode gcsTelemetryUpdateMode; /** Update mode used by the GCS */ - qint32 gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ - UpdateMode loggingUpdateMode; /** Update mode used by the logging module */ - qint32 loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */ - } Metadata; - - - UAVObject(quint32 objID, quint32 instID, bool isSingleInst, QString& name, quint32 numBytes); - quint32 getObjID(); - quint32 getInstID(); - bool isSingleInstance(); - QString getName(); - quint32 getNumBytes(); - virtual qint32 pack(quint8* dataOut) = 0; - virtual qint32 unpack(const quint8* dataIn) = 0; - virtual void setMetadata(const Metadata& mdata) = 0; - virtual Metadata getMetadata() = 0; - void requestUpdate(); - void updated(); - void lock(); - void lock(int timeoutMs); - void unlock(); - QMutex* getMutex(); - -signals: - void objectUpdated(UAVObject* obj, bool unpacked); - void updateRequested(UAVObject* obj); - -protected: - quint32 objID; - quint32 instID; - bool isSingleInst; - QString name; - quint32 numBytes; - QMutex* mutex; - -}; - -#endif // UAVOBJECT_H +#ifndef UAVOBJECT_H +#define UAVOBJECT_H + +#include +#include +#include +#include +#include +#include +#include "uavobjectfield.h" + +class UAVObjectField; + +class UAVObject: public QObject +{ + Q_OBJECT + +public: + + /** + * Object update mode + */ + typedef enum { + UPDATEMODE_PERIODIC = 0, /** Automatically update object at periodic intervals */ + UPDATEMODE_ONCHANGE = 1, /** Only update object when its data changes */ + UPDATEMODE_MANUAL = 2, /** Manually update object, by calling the updated() function */ + UPDATEMODE_NEVER = 3 /** Object is never updated */ + } UpdateMode; + + /** + * Object metadata, each object has a meta object that holds its metadata. The metadata define + * properties for each object and can be used by multiple modules (e.g. telemetry and logger) + */ + typedef struct { + quint8 ackRequired; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */ + quint8 flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */ + qint32 flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */ + quint8 gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */ + qint32 gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */ + quint8 loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */ + qint32 loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */ + } __attribute__((packed)) Metadata; + + + UAVObject(quint32 objID, bool isSingleInst, const QString& name); + void initialize(quint32 instID); + quint32 getObjID(); + quint32 getInstID(); + bool isSingleInstance(); + QString getName(); + quint32 getNumBytes(); + virtual qint32 pack(quint8* dataOut); + virtual qint32 unpack(const quint8* dataIn); + virtual void setMetadata(const Metadata& mdata) = 0; + virtual Metadata getMetadata() = 0; + virtual Metadata getDefaultMetadata() = 0; + void requestUpdate(); + void updated(); + void lock(); + void lock(int timeoutMs); + void unlock(); + QMutex* getMutex(); + qint32 getNumFields(); + QList getFields(); + UAVObjectField* getField(QString& name); + QString toString(); + QString toStringBrief(); + QString toStringData(); + +signals: + void objectUpdated(UAVObject* obj); + void objectUpdatedAuto(UAVObject* obj); + void objectUpdatedManual(UAVObject* obj); + void objectUnpacked(UAVObject* obj); + void updateRequested(UAVObject* obj); + +private slots: + void fieldUpdated(UAVObjectField* field); + +protected: + quint32 objID; + quint32 instID; + bool isSingleInst; + QString name; + quint32 numBytes; + QMutex* mutex; + quint8* data; + QList fields; + + void initializeFields(QList& fields, quint8* data, quint32 numBytes); +}; + +#endif // UAVOBJECT_H diff --git a/ground/src/plugins/uavobjects/uavobjectfield.cpp b/ground/src/plugins/uavobjects/uavobjectfield.cpp index e6ad2e536..66efe0a23 100644 --- a/ground/src/plugins/uavobjects/uavobjectfield.cpp +++ b/ground/src/plugins/uavobjects/uavobjectfield.cpp @@ -25,206 +25,280 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "uavobjectfield.h" -#include - -UAVObjectField::UAVObjectField(QString& name, QString& units, FieldType type, quint32 numElements) -{ - // Copy params - this->name = name; - this->units = units; - this->type = type; - this->numElements = numElements; - this->offset = 0; - this->data = NULL; - this->obj = NULL; - // Calculate the number of bytes per element based on the type - switch (type) { - case FIELDTYPE_CHAR: - case FIELDTYPE_INT8: - this->numBytesPerElement = 1; - break; - case FIELDTYPE_INT16: - this->numBytesPerElement = 2; - break; - case FIELDTYPE_INT32: - case FIELDTYPE_FLOAT32: - this->numBytesPerElement = 4; - break; - default: - this->numBytesPerElement = 0; - } -} - -void UAVObjectField::initialize(quint8* data, quint32 dataOffset, UAVObject* obj) -{ - this->data = data; - this->offset = dataOffset; - this->obj = obj; - clear(); -} - -UAVObject* UAVObjectField::getObject() -{ - return obj; -} - -void UAVObjectField::clear() -{ - if (data != NULL) - { - QMutexLocker locker(obj->getMutex()); - for (unsigned int n = 0; n < numBytesPerElement*numElements; ++n) - { - data[offset + n] = 0; - } - } -} - -QString UAVObjectField::getName() -{ - return name; -} - -QString UAVObjectField::getUnits() -{ - return units; -} - -UAVObjectField::FieldType UAVObjectField::getType() -{ - return type; -} - -quint32 UAVObjectField::getNumElements() -{ - return numElements; -} - - -double UAVObjectField::getValue(quint32 index) -{ - double ret = 0.0; - - // Check if index is out of bounds or no data available - if (index < numElements && data != NULL) - { - // Get value from data - QMutexLocker locker(obj->getMutex()); - switch (type) { - case FIELDTYPE_CHAR: - case FIELDTYPE_INT8: - qint8 value8; - value8 = data[offset + numBytesPerElement*index]; - ret = (double)value8; - break; - case FIELDTYPE_INT16: - qint16 value16; - value16 = (qint16)qFromBigEndian(&data[offset + numBytesPerElement*index]); - ret = (double)value16; - break; - case FIELDTYPE_INT32: - qint32 value32; - value32 = (qint32)qFromBigEndian(&data[offset + numBytesPerElement*index]); - ret = (double)value32; - break; - case FIELDTYPE_FLOAT32: - qint32 tmp; - float valuef; - tmp = (qint32)qFromBigEndian(&data[offset + numBytesPerElement*index]); - memcpy(&valuef, &tmp, 4); - ret = (double)valuef; - break; - default: - ret = 0.0; - } - } - return ret; -} - -void UAVObjectField::setValue(double value, quint32 index) -{ - // Check if index is out of bounds or no data available - if (index < numElements && data != NULL) - { - // Set value - QMutexLocker locker(obj->getMutex()); - switch (type) { - case FIELDTYPE_CHAR: - case FIELDTYPE_INT8: - data[offset + numBytesPerElement*index] = (qint8)value; - break; - case FIELDTYPE_INT16: - qToBigEndian((qint16)value, &data[offset + numBytesPerElement*index]); - break; - case FIELDTYPE_INT32: - qToBigEndian((qint32)value, &data[offset + numBytesPerElement*index]); - break; - case FIELDTYPE_FLOAT32: - qint32 tmp; - memcpy(&tmp, &value, 4); - qToBigEndian((qint32)tmp, &data[offset + numBytesPerElement*index]); - break; - } - } - - // Emit updated event - emit fieldUpdated(this); -} - -double UAVObjectField::getValue() -{ - return getValue(0); -} - -void UAVObjectField::setValue(double value) -{ - setValue(value, 0); -} - - -QString UAVObjectField::getString() -{ - QString str; - if (data != NULL) - { - QMutexLocker locker(obj->getMutex()); - data[offset + numElements - 1] = '\0'; // null terminate - if (type == FIELDTYPE_CHAR) - { - str.append((char*)&data[offset]); - } - } - return str; -} - -void UAVObjectField::setString(QString& str) -{ - QByteArray barray = str.toAscii(); - if (data != NULL) - { - QMutexLocker locker(obj->getMutex()); - for (int n = 0; n < barray.length() && n < (int)numElements; ++n) - { - data[offset+n] = barray[n]; - } - data[offset + numElements - 1] = '\0'; // null terminate - } -} - -quint32 UAVObjectField::getDataOffset() -{ - return offset; -} - -quint32 UAVObjectField::getNumBytes() -{ - return numBytesPerElement * numElements; -} - -quint32 UAVObjectField::getNumBytesElement() -{ - return numBytesPerElement; -} - - +#include "uavobjectfield.h" +#include + +UAVObjectField::UAVObjectField(const QString& name, const QString& units, FieldType type, quint32 numElements) +{ + // Copy params + this->name = name; + this->units = units; + this->type = type; + this->numElements = numElements; + this->offset = 0; + this->data = NULL; + this->obj = NULL; + // Calculate the number of bytes per element based on the type + switch (type) { + case FIELDTYPE_CHAR: + case FIELDTYPE_INT8: + this->numBytesPerElement = 1; + break; + case FIELDTYPE_INT16: + this->numBytesPerElement = 2; + break; + case FIELDTYPE_INT32: + case FIELDTYPE_FLOAT32: + this->numBytesPerElement = 4; + break; + default: + this->numBytesPerElement = 0; + } +} + +void UAVObjectField::initialize(quint8* data, quint32 dataOffset, UAVObject* obj) +{ + this->data = data; + this->offset = dataOffset; + this->obj = obj; + clear(); +} + +UAVObject* UAVObjectField::getObject() +{ + return obj; +} + +void UAVObjectField::clear() +{ + if (data != NULL) + { + QMutexLocker locker(obj->getMutex()); + for (unsigned int n = 0; n < numBytesPerElement*numElements; ++n) + { + data[offset + n] = 0; + } + } +} + +QString UAVObjectField::getName() +{ + return name; +} + +QString UAVObjectField::getUnits() +{ + return units; +} + +UAVObjectField::FieldType UAVObjectField::getType() +{ + return type; +} + +quint32 UAVObjectField::getNumElements() +{ + return numElements; +} + +qint32 UAVObjectField::pack(quint8* dataOut) +{ + QMutexLocker locker(obj->getMutex()); + // Pack each element in output buffer + for (quint32 index = 0; index < numElements; ++index) + { + switch (type) { + case FIELDTYPE_CHAR: + case FIELDTYPE_INT8: + dataOut[numBytesPerElement*index] = data[offset + numBytesPerElement*index]; + break; + case FIELDTYPE_INT16: + qint16 value16; + memcpy(&value16, &data[offset + numBytesPerElement*index], 2); + qToBigEndian(value16, &dataOut[numBytesPerElement*index]); + break; + case FIELDTYPE_INT32: + case FIELDTYPE_FLOAT32: + qint32 value32; + memcpy(&value32, &data[offset + numBytesPerElement*index], 4); + qToBigEndian(value32, &dataOut[numBytesPerElement*index]); + break; + default: + return 0; + } + } + // Done + return getNumBytes(); +} + +qint32 UAVObjectField::unpack(const quint8* dataIn) +{ + QMutexLocker locker(obj->getMutex()); + // Pack each element in output buffer + for (quint32 index = 0; index < numElements; ++index) + { + switch (type) { + case FIELDTYPE_CHAR: + case FIELDTYPE_INT8: + data[offset + numBytesPerElement*index] = dataIn[numBytesPerElement*index]; + break; + case FIELDTYPE_INT16: + qint16 value16; + value16 = qFromBigEndian(&dataIn[numBytesPerElement*index]); + memcpy(&data[offset + numBytesPerElement*index], &value16, 2); + break; + case FIELDTYPE_INT32: + case FIELDTYPE_FLOAT32: + qint32 value32; + value32 = qFromBigEndian(&dataIn[numBytesPerElement*index]); + memcpy(&data[offset + numBytesPerElement*index], &value32, 4); + break; + default: + return 0; + } + } + // Done + return getNumBytes(); +} + +double UAVObjectField::getValue(quint32 index) +{ + double ret = 0.0; + + // Check if index is out of bounds or no data available + if (index < numElements && data != NULL) + { + // Get value from data + QMutexLocker locker(obj->getMutex()); + switch (type) { + case FIELDTYPE_CHAR: + case FIELDTYPE_INT8: + qint8 value8; + value8 = data[offset + numBytesPerElement*index]; + ret = (double)value8; + break; + case FIELDTYPE_INT16: + qint16 value16; + memcpy(&value16, &data[offset + numBytesPerElement*index], 2); + ret = (double)value16; + break; + case FIELDTYPE_INT32: + qint32 value32; + memcpy(&value32, &data[offset + numBytesPerElement*index], 4); + ret = (double)value32; + break; + case FIELDTYPE_FLOAT32: + float valuef; + memcpy(&valuef, &data[offset + numBytesPerElement*index], 4); + ret = (double)valuef; + break; + default: + ret = 0.0; + } + } + return ret; +} + +void UAVObjectField::setValue(double value, quint32 index) +{ + // Check if index is out of bounds or no data available + if (index < numElements && data != NULL) + { + // Set value + QMutexLocker locker(obj->getMutex()); + switch (type) { + case FIELDTYPE_CHAR: + case FIELDTYPE_INT8: + data[offset + numBytesPerElement*index] = (qint8)value; + break; + case FIELDTYPE_INT16: + qint16 value16; + value16 = (qint16)value; + memcpy(&data[offset + numBytesPerElement*index], &value16, 2); + break; + case FIELDTYPE_INT32: + qint32 value32; + value32 = (qint32)value; + memcpy(&data[offset + numBytesPerElement*index], &value32, 4); + break; + case FIELDTYPE_FLOAT32: + float valuef; + valuef = (float)value; + memcpy(&data[offset + numBytesPerElement*index], &valuef, 4); + break; + } + } + + // Emit updated event + emit fieldUpdated(this); +} + +double UAVObjectField::getValue() +{ + return getValue(0); +} + +void UAVObjectField::setValue(double value) +{ + setValue(value, 0); +} + + +QString UAVObjectField::getString() +{ + QString str; + if (data != NULL) + { + QMutexLocker locker(obj->getMutex()); + data[offset + numElements - 1] = '\0'; // null terminate + if (type == FIELDTYPE_CHAR) + { + str.append((char*)&data[offset]); + } + } + return str; +} + +void UAVObjectField::setString(QString& str) +{ + QByteArray barray = str.toAscii(); + if (data != NULL) + { + QMutexLocker locker(obj->getMutex()); + for (int n = 0; n < barray.length() && n < (int)numElements; ++n) + { + data[offset+n] = barray[n]; + } + data[offset + numElements - 1] = '\0'; // null terminate + } +} + +quint32 UAVObjectField::getDataOffset() +{ + return offset; +} + +quint32 UAVObjectField::getNumBytes() +{ + return numBytesPerElement * numElements; +} + +quint32 UAVObjectField::getNumBytesElement() +{ + return numBytesPerElement; +} + +QString UAVObjectField::toString() +{ + QString sout; + sout.append ( QString("%1: [ ").arg(name) ); + for (unsigned int n = 0; n < numElements; ++n) + { + sout.append( QString("%1 ").arg(getValue(n)) ); + } + sout.append( QString("] %1\n").arg(units) ); + return sout; +} + + + diff --git a/ground/src/plugins/uavobjects/uavobjectfield.h b/ground/src/plugins/uavobjects/uavobjectfield.h index 285262bfd..29dc28e58 100644 --- a/ground/src/plugins/uavobjects/uavobjectfield.h +++ b/ground/src/plugins/uavobjects/uavobjectfield.h @@ -25,60 +25,65 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef UAVOBJECTFIELD_H -#define UAVOBJECTFIELD_H - -#include "uavobject.h" - -class UAVObjectField: public QObject -{ - Q_OBJECT - -public: - /** - * Recognized field types - */ - typedef enum { - FIELDTYPE_INT8 = 0, - FIELDTYPE_INT16, - FIELDTYPE_INT32, - FIELDTYPE_FLOAT32, - FIELDTYPE_CHAR - } FieldType; - - UAVObjectField(QString& name, QString& units, FieldType type, quint32 numElements); - void initialize(quint8* data, quint32 dataOffset, UAVObject* obj); - UAVObject* getObject(); - QString getName(); - QString getUnits(); - FieldType getType(); - quint32 getNumElements(); - double getValue(); - void setValue(double value); - double getValue(quint32 index); - void setValue(double value, quint32 index); - QString getString(); - void setString(QString& str); - quint32 getDataOffset(); - quint32 getNumBytes(); - quint32 getNumBytesElement(); - -signals: - void fieldUpdated(UAVObjectField* field); - -private: - QString name; - QString units; - FieldType type; - quint32 numElements; - quint32 numBytesPerElement; - quint32 offset; - quint8* data; - UAVObject* obj; - - void clear(); - - -}; - -#endif // UAVOBJECTFIELD_H +#ifndef UAVOBJECTFIELD_H +#define UAVOBJECTFIELD_H + +#include "uavobject.h" + +class UAVObject; + +class UAVObjectField: public QObject +{ + Q_OBJECT + +public: + /** + * Recognized field types + */ + typedef enum { + FIELDTYPE_INT8 = 0, + FIELDTYPE_INT16, + FIELDTYPE_INT32, + FIELDTYPE_FLOAT32, + FIELDTYPE_CHAR + } FieldType; + + UAVObjectField(const QString& name, const QString& units, FieldType type, quint32 numElements); + void initialize(quint8* data, quint32 dataOffset, UAVObject* obj); + UAVObject* getObject(); + QString getName(); + QString getUnits(); + FieldType getType(); + quint32 getNumElements(); + qint32 pack(quint8* dataOut); + qint32 unpack(const quint8* dataIn); + double getValue(); + void setValue(double value); + double getValue(quint32 index); + void setValue(double value, quint32 index); + QString getString(); + void setString(QString& str); + quint32 getDataOffset(); + quint32 getNumBytes(); + quint32 getNumBytesElement(); + QString toString(); + +signals: + void fieldUpdated(UAVObjectField* field); + +private: + QString name; + QString units; + FieldType type; + quint32 numElements; + quint32 numBytesPerElement; + quint32 offset; + quint8* data; + UAVObject* obj; + + void clear(); + + +}; + +#endif // UAVOBJECTFIELD_H diff --git a/ground/src/plugins/uavobjects/uavobjectmanager.cpp b/ground/src/plugins/uavobjects/uavobjectmanager.cpp index 1ede51699..d7c596fa8 100644 --- a/ground/src/plugins/uavobjects/uavobjectmanager.cpp +++ b/ground/src/plugins/uavobjects/uavobjectmanager.cpp @@ -25,278 +25,311 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "uavobjectmanager.h" - -UAVObjectManager::UAVObjectManager() -{ - mutex = new QMutex(QMutex::Recursive); -} - -bool UAVObjectManager::registerObject(UAVObject* obj) -{ - QMutexLocker locker(mutex); - // Check if this object type is already in the list - for (int objidx = 0; objidx < objects.length(); ++objidx) - { - // Check if the object ID is in the list - if (objects[objidx].length() > 0 && objects[objidx][0]->getObjID() == obj->getObjID()) - { - // Check if the instance is already in the list - for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) - { - if ( objects[objidx][instidx]->getInstID() == obj->getInstID() ) - { - // Object already registered, do not add - return false; - } - } - // If this point is reached, the object is not in the list, so now we can add it in the existing list - objects[objidx].append(obj); - emit newObject(obj); - return true; - } - } - // If this point is reached then this is the first time this object ID is added in the list - // create a new list of the instances and add in the object collection. - QList list; - list.append(obj); - objects.append(list); - emit newObject(obj); - return true; -} - -UAVDataObject* UAVObjectManager::newObjectInstance(QString& name, quint32 instId) -{ - return newObjectInstance(&name, 0, instId); -} - -UAVDataObject* UAVObjectManager::newObjectInstance(quint32 objId, quint32 instId) -{ - return newObjectInstance(NULL, objId, instId); -} - -UAVDataObject* UAVObjectManager::newObjectInstance(QString* name, quint32 objId, quint32 instId) -{ - QMutexLocker locker(mutex); - // Get object of the same name from collection - UAVObject* tmpObj; - if (name != NULL) - { - tmpObj = getObject(*name); - } - else - { - tmpObj = getObject(objId); - } - if (tmpObj == NULL) - { - return NULL; - } - // Make sure this is a data object - UAVDataObject* refObj = dynamic_cast(tmpObj); - if (refObj == NULL) - { - return NULL; - } - // Check if this is single instance object - if (refObj->isSingleInstance()) - { - return NULL; - } - // Make a deep copy of the fields in the reference object - QList fields; - QList refFields = refObj->getFields(); - for (int n = 0; n < refFields.length(); ++n) - { - QString fname = refFields[n]->getName(); - QString funits = refFields[n]->getUnits(); - UAVObjectField* field = new UAVObjectField(fname, funits, refFields[n]->getType(), - refFields[n]->getNumElements()); - - fields.append(field); - } - // Calculate instance ID, if the one specified is 0 - // (the first object registered always gets the instance ID of zero, so any new instances will be >1) - if (instId == 0) - { - instId = getNumInstances(tmpObj->getObjID()) + 1; - } - // Create new instance, by using properties from reference object - QString oname = refObj->getName(); - UAVDataObject* obj = new UAVDataObject(refObj->getObjID(), instId, refObj->isSingleInstance(), - oname, refObj->getNumBytes()); - obj->initialize(fields, refObj->getMetaObject()); - // Register - registerObject(obj); - // Trigger update - obj->updated(); - return obj; -} - -QList< QList > UAVObjectManager::getObjects() -{ - QMutexLocker locker(mutex); - return objects; -} - -QList< QList > UAVObjectManager::getDataObjects() -{ - QMutexLocker locker(mutex); - QList< QList > dObjects; - - // Go through objects and copy to new list when types match - for (int objidx = 0; objidx < objects.length(); ++objidx) - { - if (objects[objidx].length() > 0) - { - // Check type - UAVDataObject* obj = dynamic_cast(objects[objidx][0]); - if (obj != NULL) - { - // Create instance list - QList list; - // Go through instances and cast them to UAVDataObject, then add to list - for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) - { - obj = dynamic_cast(objects[objidx][instidx]); - if (obj != NULL) - { - list.append(obj); - } - } - // Append to object list - dObjects.append(list); - } - } - } - // Done - return dObjects; -} - -QList > UAVObjectManager::getMetaObjects() -{ - QMutexLocker locker(mutex); - QList< QList > mObjects; - - // Go through objects and copy to new list when types match - for (int objidx = 0; objidx < objects.length(); ++objidx) - { - if (objects[objidx].length() > 0) - { - // Check type - UAVMetaObject* obj = dynamic_cast(objects[objidx][0]); - if (obj != NULL) - { - // Create instance list - QList list; - // Go through instances and cast them to UAVMetaObject, then add to list - for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) - { - obj = dynamic_cast(objects[objidx][instidx]); - if (obj != NULL) - { - list.append(obj); - } - } - // Append to object list - mObjects.append(list); - } - } - } - // Done - return mObjects; -} - -UAVObject* UAVObjectManager::getObject(QString& name, quint32 instId) -{ - return getObject(&name, 0, instId); -} - -UAVObject* UAVObjectManager::getObject(quint32 objId, quint32 instId) -{ - return getObject(NULL, objId, instId); -} - -UAVObject* UAVObjectManager::getObject(QString* name, quint32 objId, quint32 instId) -{ - QMutexLocker locker(mutex); - // Check if this object type is already in the list - for (int objidx = 0; objidx < objects.length(); ++objidx) - { - // Check if the object ID is in the list - if (objects[objidx].length() > 0) - { - if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) ) - { - // Look for the requested instance ID - for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) - { - if (objects[objidx][instidx]->getInstID() == instId) - { - return objects[objidx][instidx]; - } - } - } - } - } - // If this point is reached then the requested object could not be found - return NULL; -} - -QList UAVObjectManager::getObjectInstances(QString& name) -{ - return getObjectInstances(&name, 0); -} - -QList UAVObjectManager::getObjectInstances(quint32 objId) -{ - return getObjectInstances(NULL, objId); -} - -QList UAVObjectManager::getObjectInstances(QString* name, quint32 objId) -{ - QMutexLocker locker(mutex); - // Check if this object type is already in the list - for (int objidx = 0; objidx < objects.length(); ++objidx) - { - // Check if the object ID is in the list - if (objects[objidx].length() > 0) - { - if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) ) - { - return objects[objidx]; - } - } - } - // If this point is reached then the requested object could not be found - return QList(); -} - -qint32 UAVObjectManager::getNumInstances(QString& name) -{ - return getNumInstances(&name, 0); -} - -qint32 UAVObjectManager::getNumInstances(quint32 objId) -{ - return getNumInstances(NULL, objId); -} - -qint32 UAVObjectManager::getNumInstances(QString* name, quint32 objId) -{ - QMutexLocker locker(mutex); - // Check if this object type is already in the list - for (int objidx = 0; objidx < objects.length(); ++objidx) - { - // Check if the object ID is in the list - if (objects[objidx].length() > 0) - { - if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) ) - { - return objects[objidx].length(); - } - } - } - // If this point is reached then the requested object could not be found - return -1; -} +#include "uavobjectmanager.h" + +/** + * Constructor + */ +UAVObjectManager::UAVObjectManager() +{ + mutex = new QMutex(QMutex::Recursive); +} + +/** + * Register an object with the manager. This function must be called for all newly created instances. + * A new instance can be created directly by instantiating a new object or by calling clone() of + * an existing object. The object will be registered and will be properly initialized so that it can accept + * updates. + */ +bool UAVObjectManager::registerObject(UAVDataObject* obj) +{ + QMutexLocker locker(mutex); + // Check if this object type is already in the list + for (int objidx = 0; objidx < objects.length(); ++objidx) + { + // Check if the object ID is in the list + if (objects[objidx].length() > 0 && objects[objidx][0]->getObjID() == obj->getObjID()) + { + // Check if this is a single instance object, if yes we can not add a new instance + if (obj->isSingleInstance()) + { + return false; + } + // The object type has alredy been added, so now we need to initialize the new instance with the appropriate id + // There is a single metaobject for all object instances of this type, so no need to create a new one + // Get object type metaobject from existing instance + UAVDataObject* refObj = dynamic_cast(objects[objidx][0]); + if (refObj == NULL) + { + return false; + } + UAVMetaObject* mobj = refObj->getMetaObject(); + // If the instance ID is specified and not at the default value (0) then we need to make sure + // that there are no gaps in the instance list. If gaps are found then then additional instances + // will be created. + if ( (obj->getInstID() > 0) && (obj->getInstID() < MAX_INSTANCES) ) + { + for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) + { + if ( objects[objidx][instidx]->getInstID() == obj->getInstID() ) + { + // Instance conflict, do not add + return false; + } + } + // Check if there are any gaps between the requested instance ID and the ones in the list, + // if any then create the missing instances. + for (quint32 instidx = objects[objidx].length(); instidx < obj->getInstID(); ++instidx) + { + UAVDataObject* cobj = obj->clone(instidx); + cobj->initialize(mobj); + objects[objidx].append(cobj); + emit newInstance(cobj); + } + // Finally, initialize the actual object instance + obj->initialize(mobj); + } + else if (obj->getInstID() == 0) + { + // Assign the next available ID and initialize the object instance + obj->initialize(objects[objidx].length(), mobj); + } + else + { + return false; + } + // Add the actual object instance in the list + objects[objidx].append(obj); + emit newInstance(obj); + return true; + } + } + // If this point is reached then this is the first time this object type (ID) is added in the list + // create a new list of the instances, add in the object collection and create the object's metaobject + // Create metaobject + QString mname = obj->getName(); + mname.append("Meta"); + UAVMetaObject* mobj = new UAVMetaObject(obj->getObjID()+1, mname, obj); + // Initialize object + obj->initialize(0, mobj); + // Add to list + addObject(obj); + addObject(mobj); + return true; +} + +void UAVObjectManager::addObject(UAVObject* obj) +{ + // Add to list + QList list; + list.append(obj); + objects.append(list); + emit newObject(obj); +} + +/** + * Get all objects. A two dimentional QList is returned. Objects are grouped by + * instances of the same object type. + */ +QList< QList > UAVObjectManager::getObjects() +{ + QMutexLocker locker(mutex); + return objects; +} + +/** + * Same as getObjects() but will only return DataObjects. + */ +QList< QList > UAVObjectManager::getDataObjects() +{ + QMutexLocker locker(mutex); + QList< QList > dObjects; + + // Go through objects and copy to new list when types match + for (int objidx = 0; objidx < objects.length(); ++objidx) + { + if (objects[objidx].length() > 0) + { + // Check type + UAVDataObject* obj = dynamic_cast(objects[objidx][0]); + if (obj != NULL) + { + // Create instance list + QList list; + // Go through instances and cast them to UAVDataObject, then add to list + for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) + { + obj = dynamic_cast(objects[objidx][instidx]); + if (obj != NULL) + { + list.append(obj); + } + } + // Append to object list + dObjects.append(list); + } + } + } + // Done + return dObjects; +} + +/** + * Same as getObjects() but will only return MetaObjects. + */ +QList > UAVObjectManager::getMetaObjects() +{ + QMutexLocker locker(mutex); + QList< QList > mObjects; + + // Go through objects and copy to new list when types match + for (int objidx = 0; objidx < objects.length(); ++objidx) + { + if (objects[objidx].length() > 0) + { + // Check type + UAVMetaObject* obj = dynamic_cast(objects[objidx][0]); + if (obj != NULL) + { + // Create instance list + QList list; + // Go through instances and cast them to UAVMetaObject, then add to list + for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) + { + obj = dynamic_cast(objects[objidx][instidx]); + if (obj != NULL) + { + list.append(obj); + } + } + // Append to object list + mObjects.append(list); + } + } + } + // Done + return mObjects; +} + +/** + * Get a specific object given its name and instance ID + * @returns The object is found or NULL if not + */ +UAVObject* UAVObjectManager::getObject(QString& name, quint32 instId) +{ + return getObject(&name, 0, instId); +} + +/** + * Get a specific object given its object and instance ID + * @returns The object is found or NULL if not + */ +UAVObject* UAVObjectManager::getObject(quint32 objId, quint32 instId) +{ + return getObject(NULL, objId, instId); +} + +/** + * Helper function for the public getObject() functions. + */ +UAVObject* UAVObjectManager::getObject(QString* name, quint32 objId, quint32 instId) +{ + QMutexLocker locker(mutex); + // Check if this object type is already in the list + for (int objidx = 0; objidx < objects.length(); ++objidx) + { + // Check if the object ID is in the list + if (objects[objidx].length() > 0) + { + if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) ) + { + // Look for the requested instance ID + for (int instidx = 0; instidx < objects[objidx].length(); ++instidx) + { + if (objects[objidx][instidx]->getInstID() == instId) + { + return objects[objidx][instidx]; + } + } + } + } + } + // If this point is reached then the requested object could not be found + return NULL; +} + +/** + * Get all the instances of the object specified by name + */ +QList UAVObjectManager::getObjectInstances(QString& name) +{ + return getObjectInstances(&name, 0); +} + +/** + * Get all the instances of the object specified by its ID + */ +QList UAVObjectManager::getObjectInstances(quint32 objId) +{ + return getObjectInstances(NULL, objId); +} + +/** + * Helper function for the public getObjectInstances() + */ +QList UAVObjectManager::getObjectInstances(QString* name, quint32 objId) +{ + QMutexLocker locker(mutex); + // Check if this object type is already in the list + for (int objidx = 0; objidx < objects.length(); ++objidx) + { + // Check if the object ID is in the list + if (objects[objidx].length() > 0) + { + if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) ) + { + return objects[objidx]; + } + } + } + // If this point is reached then the requested object could not be found + return QList(); +} + +/** + * Get the number of instances for an object given its name + */ +qint32 UAVObjectManager::getNumInstances(QString& name) +{ + return getNumInstances(&name, 0); +} + +/** + * Get the number of instances for an object given its ID + */ +qint32 UAVObjectManager::getNumInstances(quint32 objId) +{ + return getNumInstances(NULL, objId); +} + +/** + * Helper function for public getNumInstances + */ +qint32 UAVObjectManager::getNumInstances(QString* name, quint32 objId) +{ + QMutexLocker locker(mutex); + // Check if this object type is already in the list + for (int objidx = 0; objidx < objects.length(); ++objidx) + { + // Check if the object ID is in the list + if (objects[objidx].length() > 0) + { + if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) ) + { + return objects[objidx].length(); + } + } + } + // If this point is reached then the requested object could not be found + return -1; +} diff --git a/ground/src/plugins/uavobjects/uavobjectmanager.h b/ground/src/plugins/uavobjects/uavobjectmanager.h index 4a7f3cc3d..bdebe0955 100644 --- a/ground/src/plugins/uavobjects/uavobjectmanager.h +++ b/ground/src/plugins/uavobjects/uavobjectmanager.h @@ -25,47 +25,49 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef UAVOBJECTMANAGER_H -#define UAVOBJECTMANAGER_H - -#include "uavobject.h" -#include "uavdataobject.h" -#include "uavmetaobject.h" -#include -#include - -class UAVObjectManager: public QObject -{ - Q_OBJECT - -public: - UAVObjectManager(); - - bool registerObject(UAVObject* obj); - UAVDataObject* newObjectInstance(QString& name, quint32 instId = 0); - UAVDataObject* newObjectInstance(quint32 objId, quint32 instId = 0); - QList< QList > getObjects(); - QList< QList > getDataObjects(); - QList< QList > getMetaObjects(); - UAVObject* getObject(QString& name, quint32 instId = 0); - UAVObject* getObject(quint32 objId, quint32 instId = 0); - QList getObjectInstances(QString& name); - QList getObjectInstances(quint32 objId); - qint32 getNumInstances(QString& name); - qint32 getNumInstances(quint32 objId); - -signals: - void newObject(UAVObject* obj); - -private: - QList< QList > objects; - QMutex* mutex; - - UAVDataObject* newObjectInstance(QString* name, quint32 objId, quint32 instId); - UAVObject* getObject(QString* name, quint32 objId, quint32 instId); - QList getObjectInstances(QString* name, quint32 objId); - qint32 getNumInstances(QString* name, quint32 objId); -}; - - -#endif // UAVOBJECTMANAGER_H +#ifndef UAVOBJECTMANAGER_H +#define UAVOBJECTMANAGER_H + +#include "uavobject.h" +#include "uavdataobject.h" +#include "uavmetaobject.h" +#include +#include +#include + +class UAVObjectManager: public QObject +{ + Q_OBJECT + +public: + UAVObjectManager(); + + bool registerObject(UAVDataObject* obj); + QList< QList > getObjects(); + QList< QList > getDataObjects(); + QList< QList > getMetaObjects(); + UAVObject* getObject(QString& name, quint32 instId = 0); + UAVObject* getObject(quint32 objId, quint32 instId = 0); + QList getObjectInstances(QString& name); + QList getObjectInstances(quint32 objId); + qint32 getNumInstances(QString& name); + qint32 getNumInstances(quint32 objId); + +signals: + void newObject(UAVObject* obj); + void newInstance(UAVObject* obj); + +private: + static const quint32 MAX_INSTANCES = 1000; + + QList< QList > objects; + QMutex* mutex; + + void addObject(UAVObject* obj); + UAVObject* getObject(QString* name, quint32 objId, quint32 instId); + QList getObjectInstances(QString* name, quint32 objId); + qint32 getNumInstances(QString* name, quint32 objId); +}; + + +#endif // UAVOBJECTMANAGER_H diff --git a/ground/src/plugins/uavobjects/uavobjectsinit.cpp b/ground/src/plugins/uavobjects/uavobjectsinit.cpp index e959c8f9f..2c1fa5747 100644 --- a/ground/src/plugins/uavobjects/uavobjectsinit.cpp +++ b/ground/src/plugins/uavobjects/uavobjectsinit.cpp @@ -25,9 +25,13 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "uavobjectsinit.h" - -void UAVObjectsInitialize(UAVObjectManager* objMngr) -{ - //objMngr->registerObject( new TestObject() ); -} +#include "uavobjectsinit.h" + +/** + * Static function used to initialize the first instance of each object. + * For each object class an entry should be made here. + */ +void UAVObjectsInitialize(UAVObjectManager* objMngr) +{ + //objMngr->registerObject( new TestObject() ); +} diff --git a/ground/src/plugins/uavobjects/uavobjecttemplate.cpp b/ground/src/plugins/uavobjects/uavobjecttemplate.cpp index b6c9d96cc..521a15938 100644 --- a/ground/src/plugins/uavobjects/uavobjecttemplate.cpp +++ b/ground/src/plugins/uavobjects/uavobjecttemplate.cpp @@ -25,36 +25,52 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "uavobjecttemplate.h" +#include "$(NAMELC).h" -$(NAME)::$(NAME)(): UAVDataObject(OBJID, 0, SINGLEINST, NAME, NUMBYTES) +const QString $(NAME)::NAME = QString("$(NAME)"); + +$(NAME)::$(NAME)(): UAVDataObject(OBJID, SINGLEINST, NAME) { // Create fields QList fields; $(FIELDS) - // fields.append(new UAVObjectField($(FIELD_NAME), $(FIELD_UNITS), $(FIELD_TYPE), $(FIELD_NUMELEM)); - - // Create metadata - UAVObject::Metadata metadata; - metadata.ackRequired = $(ACK); - metadata.gcsTelemetryUpdateMode = $(GCSTELEM_UPDATEMODE); - metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); - metadata.flightTelemetryUpdateMode = $(FLIGHTTELEM_UPDATEMODE); - metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); - metadata.loggingUpdateMode = $(LOGGING_UPDATEMODE); - metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); + // fields.append(new UAVObjectField(QString("$(FIELD_NAME)"), QString("$(FIELD_UNITS)", UAVObjectField::$(FIELD_TYPE), $(FIELD_NUMELEM)); // Initialize object - initialize(fields, metadata); + initializeFields(fields, (quint8*)&data, NUMBYTES); } -$(NAME)Data $(NAME)::getData() +UAVObject::Metadata $(NAME)::getDefaultMetadata() { + UAVObject::Metadata metadata; + metadata.ackRequired = $(ACK); + metadata.gcsTelemetryUpdateMode = UAVObject::$(GCSTELEM_UPDATEMODE); + metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD); + metadata.flightTelemetryUpdateMode = UAVObject::$(FLIGHTTELEM_UPDATEMODE); + metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD); + metadata.loggingUpdateMode = UAVObject::$(LOGGING_UPDATEMODE); + metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD); + return metadata; +} + +$(NAME)::DataFields $(NAME)::getData() +{ + QMutexLocker locker(mutex); return data; } -void $(NAME)::setData($(NAME)Data& data) +void $(NAME)::setData(DataFields& data) { + QMutexLocker locker(mutex); this->data = data; + emit objectUpdatedAuto(this); // trigger object updated event + emit objectUpdated(this); } + +UAVDataObject* $(NAME)::clone(quint32 instID) +{ + $(NAME)* obj = new $(NAME)(); + obj->initialize(instID, this->getMetaObject()); + return obj; +} \ No newline at end of file diff --git a/ground/src/plugins/uavobjects/uavobjecttemplate.h b/ground/src/plugins/uavobjects/uavobjecttemplate.h index a5e07cecd..ec1ef861d 100644 --- a/ground/src/plugins/uavobjects/uavobjecttemplate.h +++ b/ground/src/plugins/uavobjects/uavobjecttemplate.h @@ -30,25 +30,27 @@ #include "uavdataobject.h" -class $(NAME): UAVDataObject +class $(NAME): public UAVDataObject { -public: - static const quint32 OBJID = $(OBJID); - static const QString NAME = QString($(NAME)); - static const bool SINGLEINST = $(SINGLEINST); - static const quint32 NUMBYTES = sizeof($(NAME)Data); - +public: typedef struct { $(DATAFIELDS) - } __attribute__((packed)) $(NAME)Data; + } __attribute__((packed)) DataFields; + + static const quint32 OBJID = $(OBJID); + static const QString NAME; + static const bool SINGLEINST = $(SINGLEINST); + static const quint32 NUMBYTES = sizeof(DataFields); $(NAME)(); - $(NAME)Data getData(); - void setData($(NAME)Data& data); - + DataFields getData(); + void setData(DataFields& data); + Metadata getDefaultMetadata(); + UAVDataObject* clone(quint32 instID); + private: - $(NAME)Data data; + DataFields data; };