1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-03-15 07:29:15 +01:00

Merge branch 'next' into corvuscorax/OP-1022_AH_improvements_amorale

This commit is contained in:
Corvus Corax 2013-12-07 20:08:34 +01:00
commit 1b68f9fd04
51 changed files with 2906 additions and 726 deletions

View File

@ -2491,6 +2491,17 @@
</data>
</default>
</SystemHealthGadget>
<TelemetryMonitorGadget>
<default>
<configInfo>
<locked>true</locked>
<version>0.0.0</version>
</configInfo>
<data>
<diagram>%%DATAPATH%%diagrams/default/system-health.svg</diagram>
</data>
</default>
</TelemetryMonitorGadget>
<UAVObjectBrowser>
<default>
<configInfo>

View File

@ -4,12 +4,14 @@
LogFile::LogFile(QObject *parent) :
QIODevice(parent),
lastTimeStamp(0),
lastPlayed(0),
timeOffset(0),
playbackSpeed(1.0)
m_lastTimeStamp(0),
m_lastPlayed(0),
m_timeOffset(0),
m_playbackSpeed(1.0),
m_nextTimeStamp(0),
m_useProvidedTimeStamp(false)
{
connect(&timer, SIGNAL(timeout()), this, SLOT(timerFired()));
connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerFired()));
}
/**
@ -20,8 +22,8 @@ LogFile::LogFile(QObject *parent) :
bool LogFile::open(OpenMode mode)
{
// start a timer for playback
myTime.restart();
if (file.isOpen()) {
m_myTime.restart();
if (m_file.isOpen()) {
// We end up here when doing a replay, because the connection
// manager will also try to open the QIODevice, even though we just
// opened it after selecting the file, which happens before the
@ -29,8 +31,8 @@ bool LogFile::open(OpenMode mode)
return true;
}
if (file.open(mode) == false) {
qDebug() << "Unable to open " << file.fileName() << " for logging";
if (m_file.open(mode) == false) {
qDebug() << "Unable to open " << m_file.fileName() << " for logging";
return false;
}
@ -49,25 +51,27 @@ void LogFile::close()
{
emit aboutToClose();
if (timer.isActive()) {
timer.stop();
if (m_timer.isActive()) {
m_timer.stop();
}
file.close();
m_file.close();
QIODevice::close();
}
qint64 LogFile::writeData(const char *data, qint64 dataSize)
{
if (!file.isWritable()) {
if (!m_file.isWritable()) {
return dataSize;
}
quint32 timeStamp = myTime.elapsed();
// If m_nextTimeStamp != -1 then use this timestamp instead of the timer
// This is used when saving logs from on-board logging
quint32 timeStamp = m_useProvidedTimeStamp ? m_nextTimeStamp : m_myTime.elapsed();
file.write((char *)&timeStamp, sizeof(timeStamp));
file.write((char *)&dataSize, sizeof(dataSize));
m_file.write((char *)&timeStamp, sizeof(timeStamp));
m_file.write((char *)&dataSize, sizeof(dataSize));
qint64 written = file.write(data, dataSize);
qint64 written = m_file.write(data, dataSize);
if (written != -1) {
emit bytesWritten(written);
}
@ -77,36 +81,36 @@ qint64 LogFile::writeData(const char *data, qint64 dataSize)
qint64 LogFile::readData(char *data, qint64 maxSize)
{
QMutexLocker locker(&mutex);
qint64 toRead = qMin(maxSize, (qint64)dataBuffer.size());
QMutexLocker locker(&m_mutex);
qint64 toRead = qMin(maxSize, (qint64)m_dataBuffer.size());
memcpy(data, dataBuffer.data(), toRead);
dataBuffer.remove(0, toRead);
memcpy(data, m_dataBuffer.data(), toRead);
m_dataBuffer.remove(0, toRead);
return toRead;
}
qint64 LogFile::bytesAvailable() const
{
return dataBuffer.size();
return m_dataBuffer.size();
}
void LogFile::timerFired()
{
qint64 dataSize;
if (file.bytesAvailable() > 4) {
if (m_file.bytesAvailable() > 4) {
int time;
time = myTime.elapsed();
time = m_myTime.elapsed();
// TODO: going back in time will be a problem
while ((lastPlayed + ((time - timeOffset) * playbackSpeed) > lastTimeStamp)) {
lastPlayed += ((time - timeOffset) * playbackSpeed);
if (file.bytesAvailable() < sizeof(dataSize)) {
while ((m_lastPlayed + ((time - m_timeOffset) * m_playbackSpeed) > m_lastTimeStamp)) {
m_lastPlayed += ((time - m_timeOffset) * m_playbackSpeed);
if (m_file.bytesAvailable() < sizeof(dataSize)) {
stopReplay();
return;
}
file.read((char *)&dataSize, sizeof(dataSize));
m_file.read((char *)&dataSize, sizeof(dataSize));
if (dataSize < 1 || dataSize > (1024 * 1024)) {
qDebug() << "Error: Logfile corrupted! Unlikely packet size: " << dataSize << "\n";
@ -114,34 +118,34 @@ void LogFile::timerFired()
return;
}
if (file.bytesAvailable() < dataSize) {
if (m_file.bytesAvailable() < dataSize) {
stopReplay();
return;
}
mutex.lock();
dataBuffer.append(file.read(dataSize));
mutex.unlock();
m_mutex.lock();
m_dataBuffer.append(m_file.read(dataSize));
m_mutex.unlock();
emit readyRead();
if (file.bytesAvailable() < sizeof(lastTimeStamp)) {
if (m_file.bytesAvailable() < sizeof(m_lastTimeStamp)) {
stopReplay();
return;
}
int save = lastTimeStamp;
file.read((char *)&lastTimeStamp, sizeof(lastTimeStamp));
int save = m_lastTimeStamp;
m_file.read((char *)&m_lastTimeStamp, sizeof(m_lastTimeStamp));
// some validity checks
if (lastTimeStamp < save // logfile goes back in time
|| (lastTimeStamp - save) > (60 * 60 * 1000)) { // gap of more than 60 minutes)
qDebug() << "Error: Logfile corrupted! Unlikely timestamp " << lastTimeStamp << " after " << save << "\n";
if (m_lastTimeStamp < save // logfile goes back in time
|| (m_lastTimeStamp - save) > (60 * 60 * 1000)) { // gap of more than 60 minutes)
qDebug() << "Error: Logfile corrupted! Unlikely timestamp " << m_lastTimeStamp << " after " << save << "\n";
stopReplay();
return;
}
timeOffset = time;
time = myTime.elapsed();
m_timeOffset = time;
time = m_myTime.elapsed();
}
} else {
stopReplay();
@ -150,13 +154,13 @@ void LogFile::timerFired()
bool LogFile::startReplay()
{
dataBuffer.clear();
myTime.restart();
timeOffset = 0;
lastPlayed = 0;
file.read((char *)&lastTimeStamp, sizeof(lastTimeStamp));
timer.setInterval(10);
timer.start();
m_dataBuffer.clear();
m_myTime.restart();
m_timeOffset = 0;
m_lastPlayed = 0;
m_file.read((char *)&m_lastTimeStamp, sizeof(m_lastTimeStamp));
m_timer.setInterval(10);
m_timer.start();
emit replayStarted();
return true;
}
@ -170,11 +174,11 @@ bool LogFile::stopReplay()
void LogFile::pauseReplay()
{
timer.stop();
m_timer.stop();
}
void LogFile::resumeReplay()
{
timeOffset = myTime.elapsed();
timer.start();
m_timeOffset = m_myTime.elapsed();
m_timer.start();
}

View File

@ -7,22 +7,22 @@
#include <QMutexLocker>
#include <QDebug>
#include <QBuffer>
#include "uavobjectmanager.h"
#include <math.h>
#include <QFile>
#include "utils_global.h"
class LogFile : public QIODevice {
class QTCREATOR_UTILS_EXPORT LogFile : public QIODevice {
Q_OBJECT
public:
explicit LogFile(QObject *parent = 0);
qint64 bytesAvailable() const;
qint64 bytesToWrite()
{
return file.bytesToWrite();
return m_file.bytesToWrite();
};
bool open(OpenMode mode);
void setFileName(QString name)
{
file.setFileName(name);
m_file.setFileName(name);
};
void close();
qint64 writeData(const char *data, qint64 dataSize);
@ -30,12 +30,21 @@ public:
bool startReplay();
bool stopReplay();
void useProvidedTimeStamp(bool useProvidedTimeStamp)
{
m_useProvidedTimeStamp = useProvidedTimeStamp;
}
void setNextTimeStamp(quint32 nextTimestamp)
{
m_nextTimeStamp = nextTimestamp;
}
public slots:
void setReplaySpeed(double val)
{
playbackSpeed = val;
qDebug() << "Playback speed is now" << playbackSpeed;
m_playbackSpeed = val;
qDebug() << "Playback speed is now" << m_playbackSpeed;
};
void pauseReplay();
void resumeReplay();
@ -49,17 +58,21 @@ signals:
void replayFinished();
protected:
QByteArray dataBuffer;
QTimer timer;
QTime myTime;
QFile file;
qint32 lastTimeStamp;
qint32 lastPlayed;
QMutex mutex;
QByteArray m_dataBuffer;
QTimer m_timer;
QTime m_myTime;
QFile m_file;
qint32 m_lastTimeStamp;
qint32 m_lastPlayed;
QMutex m_mutex;
int timeOffset;
double playbackSpeed;
int m_timeOffset;
double m_playbackSpeed;
private:
quint32 m_nextTimeStamp;
bool m_useProvidedTimeStamp;
};
#endif // LOGFILE_H

View File

@ -54,7 +54,8 @@ SOURCES += reloadpromptutils.cpp \
mytabwidget.cpp \
cachedsvgitem.cpp \
svgimageprovider.cpp \
hostosinfo.cpp
hostosinfo.cpp \
logfile.cpp
SOURCES += xmlconfig.cpp
@ -111,7 +112,8 @@ HEADERS += utils_global.h \
mytabwidget.h \
cachedsvgitem.h \
svgimageprovider.h \
hostosinfo.h
hostosinfo.h \
logfile.h
HEADERS += xmlconfig.h

View File

@ -48,9 +48,6 @@ ConnectionManager::ConnectionManager(Internal::MainWindow *mainWindow) :
polling(true),
m_mainWindow(mainWindow)
{
// monitor widget
m_monitorWidget = new TelemetryMonitorWidget(this);
// device list
m_availableDevList = new QComboBox;
m_availableDevList->setMinimumWidth(120);
@ -64,15 +61,14 @@ ConnectionManager::ConnectionManager(Internal::MainWindow *mainWindow) :
// put everything together
QHBoxLayout *layout = new QHBoxLayout;
layout->setSpacing(5);
layout->setContentsMargins(5, 2, 5, 2);
// cheat a bit with the margin to "nicely" center things vertically
layout->setContentsMargins(5, 0, 5, 4);
setLayout(layout);
layout->addWidget(m_monitorWidget, 0, Qt::AlignVCenter);
layout->addWidget(new QLabel(tr("Connections:")), 0, Qt::AlignVCenter);
layout->addWidget(m_availableDevList, 0, Qt::AlignVCenter);
layout->addWidget(m_connectBtn, 0, Qt::AlignVCenter);
setLayout(layout);
QObject::connect(m_connectBtn, SIGNAL(clicked()), this, SLOT(onConnectClicked()));
QObject::connect(m_availableDevList, SIGNAL(currentIndexChanged(int)), this, SLOT(onDeviceSelectionChanged(int)));
@ -87,9 +83,6 @@ ConnectionManager::~ConnectionManager()
{
disconnectDevice();
suspendPolling();
if (m_monitorWidget) {
delete m_monitorWidget;
}
}
void ConnectionManager::init()
@ -100,6 +93,15 @@ void ConnectionManager::init()
QObject::connect(ExtensionSystem::PluginManager::instance(), SIGNAL(aboutToRemoveObject(QObject *)), this, SLOT(aboutToRemoveObject(QObject *)));
}
// TODO needs documentation?
void ConnectionManager::addWidget(QWidget *widget)
{
QHBoxLayout *l = (QHBoxLayout *)layout();
l->insertWidget(0, widget, 0, Qt::AlignVCenter);
}
/**
* Method called when the user clicks the "Connect" button
*/
@ -133,11 +135,9 @@ bool ConnectionManager::connectDevice(DevListItem device)
// signal interested plugins that we connected to the device
emit deviceConnected(io_dev);
m_connectBtn->setText("Disconnect");
m_availableDevList->setEnabled(false);
// tell the monitorwidget we're conneced
m_monitorWidget->connect();
m_connectBtn->setText(tr("Disconnect"));
m_availableDevList->setEnabled(false);
return true;
}
@ -148,9 +148,6 @@ bool ConnectionManager::connectDevice(DevListItem device)
*/
bool ConnectionManager::disconnectDevice()
{
// tell the monitor widget we're disconnected
m_monitorWidget->disconnect();
if (!m_ioDev) {
// apparently we are already disconnected: this can
// happen if a plugin tries to force a disconnect whereas
@ -182,8 +179,10 @@ bool ConnectionManager::disconnectDevice()
m_connectionDevice.connection = NULL;
m_ioDev = NULL;
// signal interested plugins that we disconnected from the device
emit deviceDisconnected();
m_connectBtn->setText("Connect");
m_connectBtn->setText(tr("Connect"));
m_availableDevList->setEnabled(true);
return true;
@ -278,9 +277,6 @@ void ConnectionManager::telemetryConnected()
if (reconnectCheck->isActive()) {
reconnectCheck->stop();
}
// tell the monitor we're connected
m_monitorWidget->connect();
}
/**
@ -297,17 +293,6 @@ void ConnectionManager::telemetryDisconnected()
}
}
}
// tell the monitor we're disconnected
m_monitorWidget->disconnect();
}
/**
* Slot called when the telemetry rates are updated
*/
void ConnectionManager::telemetryUpdated(double txRate, double rxRate)
{
m_monitorWidget->updateTelemetry(txRate, rxRate);
}
void ConnectionManager::reconnectSlot()

View File

@ -31,7 +31,6 @@
#include "mainwindow.h"
#include "generalsettings.h"
#include "telemetrymonitorwidget.h"
#include <coreplugin/iconnection.h>
#include <QWidget>
#include <QtCore/QVector>
@ -104,6 +103,8 @@ public:
return m_ioDev != 0;
}
void addWidget(QWidget *widget);
bool connectDevice(DevListItem device);
bool disconnectDevice();
void suspendPolling();
@ -123,7 +124,6 @@ signals:
public slots:
void telemetryConnected();
void telemetryDisconnected();
void telemetryUpdated(double txRate, double rxRate);
private slots:
void objectAdded(QObject *obj);
@ -144,9 +144,6 @@ protected:
QLinkedList<DevListItem> m_devList;
QList<IConnection *> m_connectionsList;
// tx/rx telemetry monitor
TelemetryMonitorWidget *m_monitorWidget;
// currently connected connection plugin
DevListItem m_connectionDevice;

View File

@ -60,7 +60,6 @@
<file>images/cog.png</file>
<file>images/helpicon.svg</file>
<file>images/cpu.png</file>
<file>images/tx-rx.svg</file>
<file>qml/images/tab.png</file>
<file>qml/AboutDialog.qml</file>
<file alias="qml/AuthorsModel.qml">../../../../../build/openpilotgcs-synthetics/AuthorsModel.qml</file>

View File

@ -70,8 +70,7 @@ SOURCES += mainwindow.cpp \
uavgadgetdecorator.cpp \
workspacesettings.cpp \
uavconfiginfo.cpp \
telemetrymonitorwidget.cpp \
aboutdialog.cpp
aboutdialog.cpp \
HEADERS += mainwindow.h \
tabpositionindicator.h \
@ -130,8 +129,8 @@ HEADERS += mainwindow.h \
uavgadgetdecorator.h \
workspacesettings.h \
uavconfiginfo.h \
authorsdialog.h \
iconfigurableplugin.h \
telemetrymonitorwidget.h \
aboutdialog.h
FORMS += dialogs/settingsdialog.ui \

View File

@ -1,399 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="620.10828"
height="82.577499"
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="tx-rx.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.58"
inkscape:cx="89.172147"
inkscape:cy="14.870213"
inkscape:document-units="px"
inkscape:current-layer="txrxBackground"
showgrid="false"
showguides="false"
inkscape:guide-bbox="true"
inkscape:window-width="1440"
inkscape:window-height="686"
inkscape:window-x="200"
inkscape:window-y="200"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
borderlayer="false"
inkscape:showpageshadow="false"
showborder="true">
<sodipodi:guide
orientation="1,0"
position="5.047377,-45.228607"
id="guide3775" />
<sodipodi:guide
orientation="0,1"
position="184.31566,5.990903"
id="guide3912" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="bg"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-154.70873,-502.60486)"
style="display:inline">
<g
id="g3963">
<g
id="txrxBackground"
inkscape:label="#g3983">
<rect
style="fill:#333333;fill-rule:evenodd;stroke:#646464;stroke-width:2.57372737;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect2985"
width="617.53455"
height="80.003769"
x="155.99559"
y="503.89172"
ry="12.840112" />
<rect
style="fill:#4d4d4d;stroke:none"
id="rect3755-8"
width="53.658535"
height="25.938581"
x="222.97562"
y="512.58765"
ry="12.969291" />
<rect
style="fill:#4d4d4d;stroke:none"
id="rect3755-1-2"
width="53.658535"
height="25.169617"
x="222.09756"
y="548.42963"
ry="12.584808" />
<rect
style="fill:#4d4d4d;stroke:none"
id="rect3755-7-4"
width="53.658535"
height="25.938581"
x="282.97562"
y="512.58765"
ry="12.969291" />
<rect
style="fill:#4d4d4d;stroke:none"
id="rect3755-1-4-5"
width="53.658535"
height="25.169617"
x="282.09756"
y="548.42963"
ry="12.584808" />
<rect
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3755-5"
width="53.658535"
height="25.938581"
x="342.78049"
y="512.58765"
ry="12.969291" />
<rect
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3755-1-1"
width="53.658535"
height="25.169617"
x="341.90244"
y="548.42963"
ry="12.584808" />
<rect
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3755-7-7"
width="53.658535"
height="25.938581"
x="402.78049"
y="512.58765"
ry="12.969291" />
<rect
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3755-1-4-1"
width="53.658535"
height="25.169617"
x="401.90244"
y="548.42963"
ry="12.584808" />
<rect
style="fill:#4d4d4d;stroke:none"
id="rect3755-8-1"
width="53.658535"
height="25.938581"
x="462.78049"
y="512.58765"
ry="12.969291" />
<rect
style="fill:#4d4d4d;stroke:none"
id="rect3755-1-2-5"
width="53.658535"
height="25.169617"
x="461.90244"
y="548.42963"
ry="12.584808" />
<rect
style="fill:#4d4d4d;stroke:none"
id="rect3755-7-4-2"
width="53.658535"
height="25.938581"
x="522.78052"
y="512.58765"
ry="12.969291" />
<rect
style="fill:#4d4d4d;stroke:none"
id="rect3755-1-4-5-7"
width="53.658535"
height="25.169617"
x="521.90247"
y="548.42963"
ry="12.584808" />
<rect
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3755-7-7-4"
width="53.658535"
height="25.938581"
x="581.80487"
y="513.30939"
ry="12.969291" />
<rect
style="color:#000000;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3755-1-4-1-2"
width="53.658535"
height="25.169617"
x="580.92682"
y="549.13"
ry="12.584808" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
x="164.82353"
y="538.24451"
id="text3093"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3038"
x="164.82353"
y="538.24451">Tx</tspan></text>
<text
sodipodi:linespacing="125%"
id="text3040"
y="538.24451"
x="164.82353"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
xml:space="preserve"><tspan
y="538.24451"
x="164.82353"
id="tspan3042"
sodipodi:role="line">Tx</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
x="163.79311"
y="572.0863"
id="text3044"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3046"
x="163.79311"
y="572.0863">Rx</tspan></text>
</g>
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="tx"
style="display:inline"
transform="translate(-154.70873,-215.24268)">
<rect
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
id="tx0"
width="53.658535"
height="26.385658"
x="222.90944"
y="225.09811"
ry="13.192829"
inkscape:label="#rect3755-1-2-9" />
<rect
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
id="tx1"
width="53.658535"
height="26.385658"
x="282.90942"
y="225.09811"
ry="13.192829"
inkscape:label="#rect3755-1-4-5-3" />
<rect
style="color:#000000;fill:#00c200;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="tx2"
width="53.658535"
height="26.385658"
x="342.71429"
y="225.09811"
ry="13.192829"
inkscape:label="#rect3755-1-1-19" />
<rect
style="color:#000000;fill:#00c200;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="tx3"
width="53.658535"
height="26.385658"
x="402.71429"
y="225.09811"
ry="13.192829"
inkscape:label="#rect3755-1-4-1-8" />
<rect
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
id="tx4"
width="53.658535"
height="26.385658"
x="462.71429"
y="225.09811"
ry="13.192829"
inkscape:label="#rect3755-1-2-5-6" />
<rect
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
id="tx5"
width="53.658535"
height="26.385658"
x="522.71436"
y="225.09811"
ry="13.192829"
inkscape:label="#rect3755-1-4-5-7-5" />
<rect
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="tx6"
width="53.658535"
height="26.385658"
x="581.73871"
y="225.83234"
ry="13.192829"
inkscape:label="#rect3755-1-4-1-2-2" />
<text
xml:space="preserve"
style="font-size:28px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:Sans"
x="647.0033"
y="245.35291"
id="txSpeed"
sodipodi:linespacing="125%"
inkscape:label="#text3167"><tspan
sodipodi:role="line"
id="tspan3169"
x="647.0033"
y="245.35291">0 b/s</tspan></text>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="rx"
style="display:inline"
transform="translate(-154.70873,-215.24268)">
<rect
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
id="rx0"
width="53.658535"
height="24.722538"
x="222.35068"
y="261.28473"
ry="12.361269"
inkscape:label="#rect3755-8-12" />
<rect
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
id="rx1"
width="53.658535"
height="24.722538"
x="282.35068"
y="261.28473"
ry="12.361269"
inkscape:label="#rect3755-7-4-3" />
<rect
style="color:#000000;fill:#00c200;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rx2"
width="53.658535"
height="24.722538"
x="342.15555"
y="261.28473"
ry="12.361269"
inkscape:label="#rect3755-5-3" />
<rect
style="color:#000000;fill:#00c200;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rx3"
width="53.658535"
height="24.722538"
x="402.15555"
y="261.28473"
ry="12.361269"
inkscape:label="#rect3755-7-7-41" />
<rect
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
id="rx4"
width="53.658535"
height="24.722538"
x="462.15555"
y="261.28473"
ry="12.361269"
inkscape:label="#rect3755-8-1-1" />
<rect
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
id="rx5"
width="53.658535"
height="24.722538"
x="522.15552"
y="261.28473"
ry="12.361269"
inkscape:label="#rect3755-7-4-2-3" />
<rect
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rx6"
width="53.658535"
height="24.722538"
x="581.17987"
y="261.97269"
ry="12.361269"
inkscape:label="#rect3755-7-7-4-7" />
<text
xml:space="preserve"
style="font-size:28px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
x="646.22638"
y="281.98114"
id="rxSpeed"
sodipodi:linespacing="125%"
inkscape:label="#text3959"><tspan
sodipodi:role="line"
id="tspan3961"
x="646.22638"
y="281.98114">0 b/s</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,176 +0,0 @@
#include "telemetrymonitorwidget.h"
#include <QObject>
#include <QtGui>
#include <QFont>
#include <QDebug>
TelemetryMonitorWidget::TelemetryMonitorWidget(QWidget *parent) : QGraphicsView(parent)
{
setMinimumSize(180, 25); // From 100->25 to shorten the qwidget.
setMaximumSize(180, 25); // as above.
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setAlignment(Qt::AlignCenter);
setFrameStyle(QFrame::NoFrame);
setStyleSheet("background:transparent;");
setAttribute(Qt::WA_TranslucentBackground);
setWindowFlags(Qt::FramelessWindowHint);
QGraphicsScene *scene = new QGraphicsScene(0, 0, 180, 25, this); // keeping the scene in line with the widget for testing.
QSvgRenderer *renderer = new QSvgRenderer();
if (renderer->load(QString(":/core/images/tx-rx.svg"))) {
graph = new QGraphicsSvgItem();
graph->setSharedRenderer(renderer);
graph->setElementId("txrxBackground");
QString name;
QGraphicsSvgItem *pt;
for (int i = 0; i < NODE_NUMELEM; i++) {
name = QString("tx%0").arg(i);
if (renderer->elementExists(name)) {
pt = new QGraphicsSvgItem();
pt->setSharedRenderer(renderer);
pt->setElementId(name);
pt->setParentItem(graph);
txNodes.append(pt);
}
name = QString("rx%0").arg(i);
if (renderer->elementExists(name)) {
pt = new QGraphicsSvgItem();
pt->setSharedRenderer(renderer);
pt->setElementId(name);
pt->setParentItem(graph);
rxNodes.append(pt);
}
}
scene->addItem(graph);
txSpeed = new QGraphicsTextItem();
txSpeed->setDefaultTextColor(Qt::white);
txSpeed->setFont(QFont("Helvetica", 22, 2));
txSpeed->setParentItem(graph);
scene->addItem(txSpeed);
rxSpeed = new QGraphicsTextItem();
rxSpeed->setDefaultTextColor(Qt::white);
rxSpeed->setFont(QFont("Helvetica", 22, 2));
rxSpeed->setParentItem(graph);
scene->addItem(rxSpeed);
scene->setSceneRect(graph->boundingRect());
setScene(scene);
}
connected = false;
txValue = 0.0;
rxValue = 0.0;
setMin(0.0);
setMax(1200.0);
showTelemetry();
}
TelemetryMonitorWidget::~TelemetryMonitorWidget()
{
while (!txNodes.isEmpty()) {
delete txNodes.takeFirst();
}
while (!rxNodes.isEmpty()) {
delete rxNodes.takeFirst();
}
}
void TelemetryMonitorWidget::connect()
{
connected = true;
// flash the lights
updateTelemetry(maxValue, maxValue);
}
void TelemetryMonitorWidget::disconnect()
{
// flash the lights
updateTelemetry(maxValue, maxValue);
connected = false;
updateTelemetry(0.0, 0.0);
}
/*!
\brief Called by the UAVObject which got updated
Updates the numeric value and/or the icon if the dial wants this.
*/
void TelemetryMonitorWidget::updateTelemetry(double txRate, double rxRate)
{
txValue = txRate;
rxValue = rxRate;
showTelemetry();
}
// Converts the value into an percentage:
// this enables smooth movement in moveIndex below
void TelemetryMonitorWidget::showTelemetry()
{
txIndex = (txValue - minValue) / (maxValue - minValue) * NODE_NUMELEM;
rxIndex = (rxValue - minValue) / (maxValue - minValue) * NODE_NUMELEM;
if (connected) {
this->setToolTip(QString("Tx: %0 bytes/sec\nRx: %1 bytes/sec").arg(txValue).arg(rxValue));
} else {
this->setToolTip(QString("Disconnected"));
}
int i;
int nodeMargin = 8;
int leftMargin = 60;
QGraphicsItem *node;
for (i = 0; i < txNodes.count(); i++) {
node = txNodes.at(i);
node->setPos((i * (node->boundingRect().width() + nodeMargin)) + leftMargin, (node->boundingRect().height() / 2) - 2);
node->setVisible(connected && i < txIndex);
node->update();
}
for (i = 0; i < rxNodes.count(); i++) {
node = rxNodes.at(i);
node->setPos((i * (node->boundingRect().width() + nodeMargin)) + leftMargin, (node->boundingRect().height() * 2) - 2);
node->setVisible(connected && i < rxIndex);
node->update();
}
QRectF rect = graph->boundingRect();
txSpeed->setPos(rect.right() - 110, rect.top());
txSpeed->setPlainText(QString("%0").arg(txValue));
txSpeed->setVisible(connected);
rxSpeed->setPos(rect.right() - 110, rect.top() + (rect.height() / 2));
rxSpeed->setPlainText(QString("%0").arg(rxValue));
rxSpeed->setVisible(connected);
update();
}
void TelemetryMonitorWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event);
fitInView(graph, Qt::KeepAspectRatio);
}
void TelemetryMonitorWidget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
fitInView(graph, Qt::KeepAspectRatio);
}

View File

@ -0,0 +1,10 @@
<plugin name="FlightLog" version="1.0.0" compatVersion="1.0.0">
<vendor>The OpenPilot Project</vendor>
<copyright>(C) 2013 OpenPilot Project</copyright>
<license>The GNU Public License (GPL) Version 3</license>
<description>A plugin to manage flight side logs, viewing and downloading.</description>
<url>http://www.openpilot.org</url>
<dependencyList>
<dependency name="Core" version="1.0.0"/>
</dependencyList>
</plugin>

View File

@ -0,0 +1,189 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import org.openpilot 1.0
import "functions.js" as Functions
Rectangle {
width: 600
height: 400
ColumnLayout {
anchors.fill: parent
anchors.margins: 10
spacing: 10
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
border.width: 1
radius: 4
ColumnLayout {
anchors.margins: 10
anchors.fill: parent
Text {
Layout.fillWidth: true
text: "<b>" + qsTr("Log entries") + "</b>"
font.pixelSize: 12
}
TableView {
Layout.fillWidth: true
Layout.fillHeight: true
model: logManager.logEntries
itemDelegate: Text {
anchors.fill: parent
anchors.margins: 2
anchors.leftMargin: 5
font.pixelSize: 12
text: styleData.value
}
TableViewColumn {
role: "Flight"; title: qsTr("Flight"); width: 50;
delegate:
Text {
anchors.fill: parent
anchors.margins: 2
anchors.leftMargin: 5
font.pixelSize: 12
text: styleData.value + 1
}
}
TableViewColumn {
role: "FlightTime"; title: qsTr("Time"); width: 80;
delegate:
Text {
anchors.fill: parent
anchors.margins: 2
anchors.leftMargin: 5
font.pixelSize: 12
text: Functions.millisToTime(styleData.value)
}
}
TableViewColumn {
role: "Type"; title: "Type"; width: 50;
delegate:
Text {
anchors.fill: parent
anchors.margins: 2
anchors.leftMargin: 5
font.pixelSize: 12
text: {
switch(styleData.value) {
case 0 : text: qsTr("Empty"); break;
case 1 : text: qsTr("Text"); break;
case 2 : text: qsTr("UAVO"); break;
default: text: qsTr("Unknown"); break;
}
}
}
}
TableViewColumn { role: "LogString"; title: qsTr("Data"); width: 280}
}
RowLayout {
anchors.margins: 10
spacing: 10
ColumnLayout {
spacing: 10
Text {
id: totalFlights
font.pixelSize: 12
text: "<b>" + qsTr("Flights recorded: ") + "</b>" + (logStatus.Flight + 1)
}
Text {
id: totalEntries
font.pixelSize: 12
text: "<b>" + qsTr("Entries logged (free): ") + "</b>" +
logStatus.UsedSlots + " (" + logStatus.FreeSlots + ")"
}
}
Rectangle {
Layout.fillWidth: true
}
ColumnLayout {
spacing: 10
RowLayout {
Rectangle {
Layout.fillWidth: true
}
Text {
font.pixelSize: 12
text: "<b>" + qsTr("Flight to download:") + "</b>"
}
ComboBox {
id: flightCombo
enabled: !logManager.disableControls
model: logManager.flightEntries
}
}
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Rectangle {
Layout.fillWidth: true
}
Button {
text: qsTr("Download logs")
enabled: !logManager.disableControls
activeFocusOnPress: true
onClicked: logManager.retrieveLogs(flightCombo.currentIndex - 1)
}
}
}
}
}
}
RowLayout {
Layout.fillWidth: true
height: 40
Button {
id: exportButton
enabled: !logManager.disableControls && !logManager.disableExport
text: qsTr("Export...")
activeFocusOnPress: true
onClicked: logManager.exportLogs()
}
CheckBox {
id: exportRelativeTimeCB
enabled: !logManager.disableControls && !logManager.disableExport
text: qsTr("Adjust timestamps")
activeFocusOnPress: true
checked: logManager.adjustExportedTimestamps
onCheckedChanged: logManager.setAdjustExportedTimestamps(checked)
}
Button {
id: clearButton
enabled: !logManager.disableControls
text: qsTr("Clear all logs")
activeFocusOnPress: true
onClicked: logManager.clearAllLogs()
}
Rectangle {
Layout.fillWidth: true
}
Button {
id: cancelButton
enabled: logManager.disableControls
text: qsTr("Cancel")
activeFocusOnPress: true
onClicked: logManager.cancelExportLogs()
}
Button {
id: okButton
enabled: !logManager.disableControls
text: qsTr("OK")
isDefault: true
activeFocusOnPress: true
onClicked: dialog.close()
}
}
}
}

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/flightlog">
<file>FlightLogDialog.qml</file>
<file>functions.js</file>
</qresource>
</RCC>

View File

@ -0,0 +1,25 @@
TEMPLATE = lib
TARGET = FlightLog
QT += qml quick
include(../../openpilotgcsplugin.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/uavobjects/uavobjects.pri)
include(../../plugins/uavtalk/uavtalk.pri)
HEADERS += flightlogplugin.h \
flightlogmanager.h \
flightlogdialog.h
SOURCES += flightlogplugin.cpp \
flightlogmanager.cpp \
flightlogdialog.cpp
OTHER_FILES += Flightlog.pluginspec \
FlightLogDialog.qml \
functions.js
FORMS +=
RESOURCES += \
flightLog.qrc

View File

@ -0,0 +1,66 @@
/**
******************************************************************************
*
* @file flightlogdialog.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup FlightLogDialog
* @{
* @brief [Brief]
*****************************************************************************/
/*
* 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 "flightlogdialog.h"
#include <QVBoxLayout>
#include <QtQuick>
#include <QQuickView>
#include <QQmlEngine>
#include <QQmlContext>
#include "flightlogmanager.h"
FlightLogDialog::FlightLogDialog(QWidget *parent, FlightLogManager *flightLogManager) :
QDialog(parent)
{
qmlRegisterType<ExtendedDebugLogEntry>("org.openpilot", 1, 0, "DebugLogEntry");
setWindowIcon(QIcon(":/core/images/openpilot_logo_32.png"));
setWindowTitle(tr("Manage flight side logs"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setMinimumSize(600, 400);
QQuickView *view = new QQuickView();
view->rootContext()->setContextProperty("dialog", this);
view->rootContext()->setContextProperty("logStatus", flightLogManager->flightLogStatus());
view->rootContext()->setContextProperty("logManager", flightLogManager);
view->setResizeMode(QQuickView::SizeRootObjectToView);
view->setSource(QUrl("qrc:/flightlog/FlightLogDialog.qml"));
QWidget *container = QWidget::createWindowContainer(view);
container->setMinimumSize(600, 400);
container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QVBoxLayout *lay = new QVBoxLayout();
lay->setContentsMargins(0, 0, 0, 0);
setLayout(lay);
layout()->addWidget(container);
}
FlightLogDialog::~FlightLogDialog()
{}

View File

@ -0,0 +1,15 @@
#ifndef FLIGHTLOGDIALOG_H
#define FLIGHTLOGDIALOG_H
#include <QDialog>
#include "flightlogmanager.h"
class FlightLogDialog : public QDialog {
Q_OBJECT
public:
explicit FlightLogDialog(QWidget *parent, FlightLogManager *flightLogManager);
~FlightLogDialog();
};
#endif // FLIGHTLOGDIALOG_H

View File

@ -0,0 +1,311 @@
/**
******************************************************************************
*
* @file flightlogmanager.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup FlightLogManager
* @{
* @brief [Brief]
*****************************************************************************/
/*
* 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 "flightlogmanager.h"
#include "extensionsystem/pluginmanager.h"
#include <QApplication>
#include <QFileDialog>
#include "debuglogcontrol.h"
#include "uavobjecthelper.h"
#include "uavtalk/uavtalk.h"
#include "utils/logfile.h"
FlightLogManager::FlightLogManager(QObject *parent) :
QObject(parent), m_disableControls(false),
m_disableExport(true), m_cancelDownload(false),
m_adjustExportedTimestamps(true)
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
m_objectManager = pm->getObject<UAVObjectManager>();
Q_ASSERT(m_objectManager);
m_flightLogControl = DebugLogControl::GetInstance(m_objectManager);
Q_ASSERT(m_flightLogControl);
m_flightLogStatus = DebugLogStatus::GetInstance(m_objectManager);
Q_ASSERT(m_flightLogStatus);
connect(m_flightLogStatus, SIGNAL(FlightChanged(quint16)), this, SLOT(updateFlightEntries(quint16)));
m_flightLogEntry = DebugLogEntry::GetInstance(m_objectManager);
Q_ASSERT(m_flightLogEntry);
updateFlightEntries(m_flightLogStatus->getFlight());
}
FlightLogManager::~FlightLogManager()
{
while (!m_logEntries.isEmpty()) {
delete m_logEntries.takeFirst();
}
}
void addLogEntries(QQmlListProperty<ExtendedDebugLogEntry> *list, ExtendedDebugLogEntry *entry)
{
Q_UNUSED(list);
Q_UNUSED(entry);
}
int countLogEntries(QQmlListProperty<ExtendedDebugLogEntry> *list)
{
return static_cast< QList<ExtendedDebugLogEntry *> *>(list->data)->size();
}
ExtendedDebugLogEntry *logEntryAt(QQmlListProperty<ExtendedDebugLogEntry> *list, int index)
{
return static_cast< QList<ExtendedDebugLogEntry *> *>(list->data)->at(index);
}
void clearLogEntries(QQmlListProperty<ExtendedDebugLogEntry> *list)
{
return static_cast< QList<ExtendedDebugLogEntry *> *>(list->data)->clear();
}
QQmlListProperty<ExtendedDebugLogEntry> FlightLogManager::logEntries()
{
return QQmlListProperty<ExtendedDebugLogEntry>(this, &m_logEntries, &addLogEntries, &countLogEntries, &logEntryAt, &clearLogEntries);
}
QStringList FlightLogManager::flightEntries()
{
return m_flightEntries;
}
void FlightLogManager::clearAllLogs()
{
setDisableControls(true);
QApplication::setOverrideCursor(Qt::WaitCursor);
// Clear on flight side
UAVObjectUpdaterHelper updateHelper;
m_flightLogControl->setFlight(0);
m_flightLogControl->setEntry(0);
m_flightLogControl->setOperation(DebugLogControl::OPERATION_FORMATFLASH);
if (updateHelper.doObjectAndWait(m_flightLogControl, UAVTALK_TIMEOUT) == UAVObjectUpdaterHelper::SUCCESS) {
// Then empty locally
clearLogList();
}
QApplication::restoreOverrideCursor();
setDisableControls(false);
}
void FlightLogManager::clearLogList()
{
QList<ExtendedDebugLogEntry*> tmpList(m_logEntries);
m_logEntries.clear();
emit logEntriesChanged();
setDisableExport(true);
while (!tmpList.isEmpty()) {
delete tmpList.takeFirst();
}
}
void FlightLogManager::retrieveLogs(int flightToRetrieve)
{
setDisableControls(true);
QApplication::setOverrideCursor(Qt::WaitCursor);
m_cancelDownload = false;
UAVObjectUpdaterHelper updateHelper;
UAVObjectRequestHelper requestHelper;
clearLogList();
// Set up what to retrieve
int startFlight = (flightToRetrieve == -1) ? 0 : flightToRetrieve;
int endFlight = (flightToRetrieve == -1) ? m_flightLogStatus->getFlight() : flightToRetrieve;
// Prepare to send request for event retrieval
m_flightLogControl->setOperation(DebugLogControl::OPERATION_RETRIEVE);
for (int flight = startFlight; flight <= endFlight; flight++) {
m_flightLogControl->setFlight(flight);
bool gotLast = false;
int entry = 0;
while (!gotLast) {
// Send request for loading flight entry on flight side and wait for ack/nack
m_flightLogControl->setEntry(entry);
if (updateHelper.doObjectAndWait(m_flightLogControl, UAVTALK_TIMEOUT) == UAVObjectUpdaterHelper::SUCCESS &&
requestHelper.doObjectAndWait(m_flightLogEntry, UAVTALK_TIMEOUT) == UAVObjectUpdaterHelper::SUCCESS) {
if (m_flightLogEntry->getType() != DebugLogEntry::TYPE_EMPTY) {
// Ok, we retrieved the entry, and it was the correct one. clone it and add it to the list
ExtendedDebugLogEntry *logEntry = new ExtendedDebugLogEntry();
logEntry->setData(m_flightLogEntry->getData(), m_objectManager);
m_logEntries << logEntry;
// Increment to get next entry from flight side
entry++;
} else {
// We are done, not more entries on this flight
gotLast = true;
}
} else {
// We failed for some reason
break;
}
if (m_cancelDownload) {
break;
}
}
if (m_cancelDownload) {
break;
}
}
if (m_cancelDownload) {
clearLogList();
m_cancelDownload = false;
}
emit logEntriesChanged();
setDisableExport(m_logEntries.count() == 0);
QApplication::restoreOverrideCursor();
setDisableControls(false);
}
void FlightLogManager::exportLogs()
{
if(m_logEntries.isEmpty()) {
return;
}
setDisableControls(true);
QApplication::setOverrideCursor(Qt::WaitCursor);
QString fileName = QFileDialog::getSaveFileName(NULL, tr("Save Log"),
tr("OP-%0.opl").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss")),
tr("OpenPilot Log (*.opl)"));
if (!fileName.isEmpty()) {
// Loop and create a new file for each flight.
fileName = fileName.replace(QString(".opl"), QString("%1.opl"));
int currentEntry = 0;
int currentFlight = 0;
quint32 adjustedBaseTime = 0;
// Continue until all entries are exported
while(currentEntry < m_logEntries.count()) {
if (m_adjustExportedTimestamps) {
adjustedBaseTime = m_logEntries[currentEntry]->getFlightTime();
}
// Get current flight
currentFlight = m_logEntries[currentEntry]->getFlight();
LogFile logFile;
logFile.useProvidedTimeStamp(true);
// Set the file name to contain flight number
logFile.setFileName(fileName.arg(tr("_flight-%1").arg(currentFlight + 1)));
logFile.open(QIODevice::WriteOnly);
UAVTalk uavTalk(&logFile, m_objectManager);
// Export entries until no more available or flight changes
while(currentEntry < m_logEntries.count() && m_logEntries[currentEntry]->getFlight() == currentFlight) {
ExtendedDebugLogEntry* entry = m_logEntries[currentEntry];
// Only log uavobjects
if (entry->getType() == ExtendedDebugLogEntry::TYPE_UAVOBJECT) {
// Set timestamp that should be logged for this entry
logFile.setNextTimeStamp(entry->getFlightTime() - adjustedBaseTime);
// Use UAVTalk to log complete message to file
uavTalk.sendObject(entry->uavObject(), false, false);
qDebug() << entry->getFlightTime() - adjustedBaseTime << "=" << entry->toStringBrief();
}
currentEntry++;
}
logFile.close();
}
}
QApplication::restoreOverrideCursor();
setDisableControls(false);
}
void FlightLogManager::cancelExportLogs()
{
m_cancelDownload = true;
}
void FlightLogManager::updateFlightEntries(quint16 currentFlight)
{
Q_UNUSED(currentFlight);
int flights = m_flightLogStatus->getFlight();
if (m_flightEntries.count() == 0 || (m_flightEntries.count() - 1 != flights)) {
m_flightEntries.clear();
m_flightEntries << tr("All");
for(int i = 0; i <= flights; i++) {
m_flightEntries << QString::number(i + 1);
}
emit flightEntriesChanged();
}
}
ExtendedDebugLogEntry::ExtendedDebugLogEntry() : DebugLogEntry(),
m_object(0)
{}
ExtendedDebugLogEntry::~ExtendedDebugLogEntry()
{
if (m_object) {
delete m_object;
m_object = 0;
}
}
QString ExtendedDebugLogEntry::getLogString()
{
if (getType() == DebugLogEntry::TYPE_TEXT) {
return QString((const char *)getData().Data);
} else if (getType() == DebugLogEntry::TYPE_UAVOBJECT) {
return m_object->toString().replace("\n", " ").replace("\t", " ");
} else {
return "";
}
}
void ExtendedDebugLogEntry::setData(const DebugLogEntry::DataFields &data, UAVObjectManager *objectManager)
{
DebugLogEntry::setData(data);
if (getType() == DebugLogEntry::TYPE_UAVOBJECT) {
UAVDataObject *object = (UAVDataObject *)objectManager->getObject(getObjectID(), getInstanceID());
Q_ASSERT(object);
m_object = object->clone(getInstanceID());
m_object->unpack(getData().Data);
}
}

View File

@ -0,0 +1,162 @@
/**
******************************************************************************
*
* @file flightlogmanager.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup FlightLogManager
* @{
* @brief [Brief]
*****************************************************************************/
/*
* 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 FLIGHTLOGMANAGER_H
#define FLIGHTLOGMANAGER_H
#include <QObject>
#include <QList>
#include <QQmlListProperty>
#include <QSemaphore>
#include "uavobjectmanager.h"
#include "debuglogentry.h"
#include "debuglogstatus.h"
#include "debuglogcontrol.h"
class ExtendedDebugLogEntry : public DebugLogEntry {
Q_OBJECT Q_PROPERTY(QString LogString READ getLogString WRITE setLogString NOTIFY LogStringUpdated)
public:
explicit ExtendedDebugLogEntry();
~ExtendedDebugLogEntry();
QString getLogString();
UAVDataObject *uavObject()
{
return m_object;
}
void setData(const DataFields& data, UAVObjectManager *objectManager);
public slots:
void setLogString(QString arg)
{
Q_UNUSED(arg);
}
signals:
void LogStringUpdated(QString arg);
private:
UAVDataObject *m_object;
};
class FlightLogManager : public QObject {
Q_OBJECT Q_PROPERTY(DebugLogStatus *flightLogStatus READ flightLogStatus)
Q_PROPERTY(QQmlListProperty<ExtendedDebugLogEntry> logEntries READ logEntries NOTIFY logEntriesChanged)
Q_PROPERTY(QStringList flightEntries READ flightEntries NOTIFY flightEntriesChanged)
Q_PROPERTY(bool disableControls READ disableControls WRITE setDisableControls NOTIFY disableControlsChanged)
Q_PROPERTY(bool disableExport READ disableExport WRITE setDisableExport NOTIFY disableExportChanged)
Q_PROPERTY(bool adjustExportedTimestamps READ adjustExportedTimestamps WRITE setAdjustExportedTimestamps NOTIFY adjustExportedTimestampsChanged)
public:
explicit FlightLogManager(QObject *parent = 0);
~FlightLogManager();
QQmlListProperty<ExtendedDebugLogEntry> logEntries();
QStringList flightEntries();
DebugLogStatus *flightLogStatus() const
{
return m_flightLogStatus;
}
bool disableControls() const
{
return m_disableControls;
}
bool disableExport() const
{
return m_disableExport;
}
void clearLogList();
bool adjustExportedTimestamps() const
{
return m_adjustExportedTimestamps;
}
signals:
void logEntriesChanged();
void flightEntriesChanged();
void disableControlsChanged(bool arg);
void disableExportChanged(bool arg);
void adjustExportedTimestampsChanged(bool arg);
public slots:
void clearAllLogs();
void retrieveLogs(int flightToRetrieve = -1);
void exportLogs();
void cancelExportLogs();
void setDisableControls(bool arg)
{
if (m_disableControls != arg) {
m_disableControls = arg;
emit disableControlsChanged(arg);
}
}
void setDisableExport(bool arg)
{
if (m_disableExport != arg) {
m_disableExport = arg;
emit disableExportChanged(arg);
}
}
void setAdjustExportedTimestamps(bool arg)
{
if (m_adjustExportedTimestamps != arg) {
m_adjustExportedTimestamps = arg;
emit adjustExportedTimestampsChanged(arg);
}
}
private slots:
void updateFlightEntries(quint16 currentFlight);
private:
UAVObjectManager *m_objectManager;
DebugLogControl *m_flightLogControl;
DebugLogStatus *m_flightLogStatus;
DebugLogEntry *m_flightLogEntry;
QList<ExtendedDebugLogEntry *> m_logEntries;
QStringList m_flightEntries;
static const int UAVTALK_TIMEOUT = 4000;
bool m_disableControls;
bool m_disableExport;
bool m_cancelDownload;
bool m_adjustExportedTimestamps;
};
#endif // FLIGHTLOGMANAGER_H

View File

@ -0,0 +1,98 @@
/**
******************************************************************************
*
* @file flightlogplugin.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @brief A plugin to view and download flight side logs.
*****************************************************************************/
/*
* 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 "flightlogplugin.h"
#include <QDebug>
#include <QtPlugin>
#include <QStringList>
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
#include <coreplugin/modemanager.h>
#include "flightlogdialog.h"
FlightLogPlugin::FlightLogPlugin() : m_logDialog(0)
{}
FlightLogPlugin::~FlightLogPlugin()
{
shutdown();
}
bool FlightLogPlugin::initialize(const QStringList & args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
// Add Menu entry
Core::ActionManager *am = Core::ICore::instance()->actionManager();
Core::ActionContainer *ac = am->actionContainer(Core::Constants::M_TOOLS);
Core::Command *cmd = am->registerAction(new QAction(this),
"FlightLogPlugin.ShowFlightLogDialog",
QList<int>() <<
Core::Constants::C_GLOBAL_ID);
cmd->setDefaultKeySequence(QKeySequence("Ctrl+F"));
cmd->action()->setText(tr("Manage flight side logs..."));
Core::ModeManager::instance()->addAction(cmd, 1);
ac->menu()->addSeparator();
ac->appendGroup("FlightLogs");
ac->addAction(cmd, "FlightLogs");
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(ShowLogManagementDialog()));
return true;
}
void FlightLogPlugin::ShowLogManagementDialog()
{
if (!m_logDialog) {
m_logDialog = new FlightLogDialog(0, new FlightLogManager());
connect(m_logDialog, SIGNAL(finished(int)), this, SLOT(LogManagementDialogClosed()));
m_logDialog->show();
}
}
void FlightLogPlugin::LogManagementDialogClosed()
{
if (m_logDialog) {
m_logDialog->deleteLater();
m_logDialog = 0;
}
}
void FlightLogPlugin::extensionsInitialized()
{}
void FlightLogPlugin::shutdown()
{
if (m_logDialog) {
m_logDialog->close();
LogManagementDialogClosed();
}
}

View File

@ -0,0 +1,53 @@
/**
******************************************************************************
*
* @file flightlogplugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @brief A plugin to view and download flight side logs.
*****************************************************************************/
/*
* 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 FLIGHTLOGPLUGIN_H_
#define FLIGHTLOGPLUGIN_H_
#include <extensionsystem/iplugin.h>
#include "flightlogmanager.h"
#include "flightlogdialog.h"
class FlightLogPlugin : public ExtensionSystem::IPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID "OpenPilot.FlightLog")
public:
FlightLogPlugin();
~FlightLogPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString *errorString);
void shutdown();
private slots:
void ShowLogManagementDialog();
void LogManagementDialogClosed();
private:
FlightLogDialog *m_logDialog;
};
#endif /* FLIGHTLOGPLUGIN_H_ */

View File

@ -0,0 +1,20 @@
.pragma library
function millisToTime(ms) {
var secs = Math.floor(ms / 1000);
var msleft = ms % 1000;
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
return pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + ":" + pad(msleft, 3);
}
function pad(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}

View File

@ -1,25 +1,22 @@
TEMPLATE = lib
TARGET = LoggingGadget
DEFINES += LOGGING_LIBRARY
QT += svg
include(../../openpilotgcsplugin.pri)
include(logging_dependencies.pri)
HEADERS += loggingplugin.h \
logfile.h \
logginggadgetwidget.h \
logginggadget.h \
logginggadgetfactory.h
# logginggadgetconfiguration.h
# logginggadgetoptionspage.h
SOURCES += loggingplugin.cpp \
logfile.cpp \
logginggadgetwidget.cpp \
logginggadget.cpp \
logginggadgetfactory.cpp
# logginggadgetconfiguration.cpp \
# logginggadgetoptionspage.cpp
OTHER_FILES += LoggingGadget.pluginspec
FORMS += logging.ui
# logginggadgetwidget.ui \
# loggingdialog.ui

View File

@ -323,7 +323,7 @@ bool LoggingPlugin::initialize(const QStringList & args, QString *errMsg)
QList<int>() <<
Core::Constants::C_GLOBAL_ID);
cmd->setDefaultKeySequence(QKeySequence("Ctrl+L"));
cmd->action()->setText("Start logging...");
cmd->action()->setText(tr("Start logging..."));
ac->menu()->addSeparator();
ac->appendGroup("Logging");

View File

@ -35,7 +35,7 @@
#include "uavobjectmanager.h"
#include "gcstelemetrystats.h"
#include <uavtalk/uavtalk.h>
#include <logfile.h>
#include <utils/logfile.h>
#include <QThread>
#include <QQueue>

View File

@ -49,6 +49,12 @@ plugin_uavtalk.subdir = uavtalk
plugin_uavtalk.depends = plugin_uavobjects
plugin_uavtalk.depends += plugin_coreplugin
# Telemetry plugin
SUBDIRS += plugin_telemetry
plugin_telemetry.subdir = telemetry
plugin_telemetry.depends += plugin_uavtalk
plugin_telemetry.depends += plugin_coreplugin
# OPMap UAVGadget
plugin_opmap.subdir = opmap
plugin_opmap.depends = plugin_coreplugin
@ -238,3 +244,10 @@ plugin_setupwizard.depends += plugin_config
plugin_setupwizard.depends += plugin_uploader
SUBDIRS += plugin_setupwizard
# Flight Logs plugin
plugin_flightlog.subdir = flightlog
plugin_flightlog.depends = plugin_coreplugin
plugin_flightlog.depends += plugin_uavobjects
plugin_flightlog.depends += plugin_uavtalk
SUBDIRS += plugin_flightlog

View File

@ -0,0 +1,11 @@
<plugin name="Telemetry" version="1.0.0" compatVersion="1.0.0">
<vendor>The OpenPilot Project</vendor>
<copyright>(C) 2010 OpenPilot Project</copyright>
<license>The GNU Public License (GPL) Version 3</license>
<description>UAVTalk telemetry protocol</description>
<url>http://www.openpilot.org</url>
<dependencyList>
<dependency name="Core" version="1.0.0"/>
<dependency name="UAVTalk" version="1.0.0"/>
</dependencyList>
</plugin>

View File

@ -0,0 +1,397 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="620"
height="81"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="tx-rx.svg">
<defs
id="defs4">
<linearGradient
id="linearGradient3790"
osb:paint="solid">
<stop
style="stop-color:#00ffff;stop-opacity:1;"
offset="0"
id="stop3792" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="6.5619509"
inkscape:cx="421.10913"
inkscape:cy="26.137279"
inkscape:document-units="px"
inkscape:current-layer="layer2"
showgrid="false"
showguides="false"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="988"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
borderlayer="false"
inkscape:showpageshadow="false"
showborder="true">
<sodipodi:guide
orientation="1,0"
position="5.0373595,-46.290199"
id="guide3775" />
<sodipodi:guide
orientation="0,1"
position="184.30564,4.9293069"
id="guide3912" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="background"
inkscape:label="background"
inkscape:groupmode="layer"
style="display:inline">
transform="translate(0,0)"
<g
id="g3045"
inkscape:label="#g3045"
transform="translate(0,0)">
<rect
id="bg1"
ry="13"
y="0"
x="0"
height="81"
width="633"
style="fill:#333333;stroke:none" />
<text
id="txTitle"
x="13"
y="35"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
xml:space="preserve"
sodipodi:linespacing="125%"
transform="scale(1,1)"><tspan
sodipodi:role="line"
id="tspan3042"
x="13"
y="35">Tx</tspan></text>
<rect
id="tx_bg0"
ry="13"
y="10"
x="72"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg1"
ry="13"
y="10"
x="132"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg2"
ry="13"
y="10"
x="192"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg3"
ry="13"
y="10"
x="252"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg4"
ry="13"
y="10"
x="312"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg5"
ry="13"
y="10"
x="372"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="tx_bg6"
ry="13"
y="10"
x="432"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<text
id="rxTitle"
x="13"
y="71"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
xml:space="preserve"
sodipodi:linespacing="125%"
transform="scale(1,1)"><tspan
x="35"
y="71"
id="tspan3046"
sodipodi:role="line">Rx</tspan></text>
<rect
id="rx_bg0"
ry="13"
y="46"
x="72"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg1"
ry="13"
y="46"
x="132"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg2"
ry="13"
y="46"
x="192"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg3"
ry="13"
y="46"
x="252"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg4"
ry="13"
y="46"
x="312"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg5"
ry="13"
y="46"
x="372"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
<rect
id="rx_bg6"
ry="13"
y="46"
x="432"
width="54"
height="25"
style="fill:#4d4d4d;stroke:none" />
</g>
</g>
<g
id="text"
inkscape:groupmode="layer"
inkscape:label="text"
style="display:inline"
transform="translate(0,0)">
<rect
id="txSpeed"
x="499"
y="10"
width="115"
height="25"
style="fill:#4d4d4d;stroke:none" />
inkscape:label="txSpeed" />
<rect
id="rxSpeed"
x="499"
y="46"
width="115"
height="25"
style="fill:#4d4d4d;stroke:none" />
inkscape:label="rxSpeed" />
</g>
<g
id="tx"
inkscape:groupmode="layer"
inkscape:label="tx"
style="display:inline"
transform="translate(0,-100)">
<rect
id="tx0"
width="54"
height="25"
x="72"
y="10"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-2-9" />
<rect
id="tx1"
width="54"
height="25"
x="132"
y="10"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-4-5-3" />
<rect
id="tx2"
width="54"
height="25"
x="192"
y="10"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-1-19" />
<rect
id="tx3"
width="54"
height="25"
x="252"
y="10"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-4-1-8" />
<rect
id="tx4"
width="54"
height="25"
x="312"
y="10"
ry="13"
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-2-5-6" />
<rect
id="tx5"
width="54"
height="25"
x="372"
y="10"
ry="13"
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-4-5-7-5" />
<rect
id="tx6"
width="54"
height="25"
x="432"
y="10"
ry="13"
style="fill:#ff0000;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-1-4-1-2-2" />
</g>
<g
id="rx"
inkscape:groupmode="layer"
inkscape:label="rx"
style="display:inline"
transform="translate(0,-100)">
<rect
id="rx0"
width="54"
height="25"
x="72"
y="46"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-8-12" />
<rect
id="rx1"
width="54"
height="25"
x="132"
y="46"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-7-4-3" />
<rect
id="rx2"
width="54"
height="25"
x="192"
y="46"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-5-3" />
<rect
id="rx3"
width="54"
height="25"
x="252"
y="46"
ry="13"
style="fill:#00c200;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-7-7-41" />
<rect
id="rx4"
width="54"
height="25"
x="312"
y="46"
ry="13"
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-8-1-1" />
<rect
id="rx5"
width="54"
height="25"
x="372"
y="46"
ry="13"
style="fill:#ffd800;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-7-4-2-3" />
<rect
id="rx6"
width="54"
height="25"
x="432"
y="46"
ry="13"
style="fill:#ff0000;fill-opacity:1;stroke:none;display:inline"
inkscape:label="#rect3755-7-7-4-7" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -0,0 +1,52 @@
/**
******************************************************************************
*
* @file monitorgadget.cpp
* @author Philippe Renon
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup MonitorPlugin Telemetry Plugin
* @{
* @brief The Telemetry Monitor gadget
*****************************************************************************/
/*
* 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 "monitorgadget.h"
#include "monitorgadgetconfiguration.h"
#include "monitorwidget.h"
MonitorGadget::MonitorGadget(QString classId, MonitorWidget *widget, QWidget *parent) :
IUAVGadget(classId, parent), m_widget(widget)
{}
MonitorGadget::~MonitorGadget()
{
delete m_widget;
}
/*
This is called when a configuration is loaded, and updates the plugin's settings.
Careful: the plugin is already drawn before the loadConfiguration method is called the
first time, so you have to be careful not to assume all the plugin values are initialized
the first time you use them
*/
void MonitorGadget::loadConfiguration(IUAVGadgetConfiguration *config)
{
// MonitorGadgetConfiguration *m = qobject_cast<MonitorGadgetConfiguration *>(config);
// m_widget->setSystemFile(m->getSystemFile()); // Triggers widget repaint
}

View File

@ -0,0 +1,58 @@
/**
******************************************************************************
*
* @file monitorgadget.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetry
* @{
*
*****************************************************************************/
/*
* 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 MONITORGADGET_H
#define MONITORGADGET_H
#include <coreplugin/iuavgadget.h>
#include "monitorwidget.h"
// class IUAVGadget;
// class QWidget;
// class QString;
// class NotifyPluginGadgetWidget;
using namespace Core;
class MonitorGadget : public IUAVGadget {
Q_OBJECT
public:
MonitorGadget(QString classId, MonitorWidget *widget, QWidget *parent = 0);
~MonitorGadget();
QWidget *widget()
{
return m_widget;
}
void loadConfiguration(IUAVGadgetConfiguration *config);
private:
MonitorWidget *m_widget;
};
#endif // MONITORGADGET_H

View File

@ -0,0 +1,53 @@
/**
******************************************************************************
*
* @file monitorgadgetconfiguration.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup TelemetryPlugin Telemetry Plugin
* @{
* @brief A gadget that displays a 3D representation of the UAV
*****************************************************************************/
/*
* 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 "monitorgadgetconfiguration.h"
MonitorGadgetConfiguration::MonitorGadgetConfiguration(QString classId, QSettings *qSettings, QObject *parent) :
IUAVGadgetConfiguration(classId, parent)
{
// if a saved configuration exists load it
if (qSettings != 0) {}
}
IUAVGadgetConfiguration *MonitorGadgetConfiguration::clone()
{
MonitorGadgetConfiguration *mv = new MonitorGadgetConfiguration(this->classId());
return mv;
}
/**
* Saves a configuration.
*
*/
void MonitorGadgetConfiguration::saveConfig(QSettings *qSettings) const
{
// qSettings->setValue("acFilename", Utils::PathUtils().RemoveDataPath(m_acFilename));
// qSettings->setValue("bgFilename", Utils::PathUtils().RemoveDataPath(m_bgFilename));
// qSettings->setValue("enableVbo", m_enableVbo);
}

View File

@ -0,0 +1,44 @@
/**
******************************************************************************
*
* @file monitorgadgetconfiguration.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup TelemetryPlugin Telemetry Plugin
* @{
* @brief A gadget that displays telemetry connection speed monitoring
*****************************************************************************/
/*
* 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 MONITORGADGETCONFIGURATION_H
#define MONITORGADGETCONFIGURATION_H
#include <coreplugin/iuavgadgetconfiguration.h>
using namespace Core;
class MonitorGadgetConfiguration : public IUAVGadgetConfiguration {
Q_OBJECT
public:
explicit MonitorGadgetConfiguration(QString classId, QSettings *qSettings = 0, QObject *parent = 0);
void saveConfig(QSettings *settings) const;
IUAVGadgetConfiguration *clone();
};
#endif // MONITORGADGETCONFIGURATION_H

View File

@ -0,0 +1,84 @@
/**
******************************************************************************
*
* @file monitorgadgetfactory.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetryplugin
* @{
*
*****************************************************************************/
/*
* 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 "monitorgadgetfactory.h"
#include "uavtalk/telemetrymanager.h"
#include "extensionsystem/pluginmanager.h"
#include "monitorgadgetconfiguration.h"
#include "monitorgadget.h"
#include "monitorgadgetoptionspage.h"
#include <coreplugin/connectionmanager.h>
#include <coreplugin/icore.h>
MonitorGadgetFactory::MonitorGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("TelemetryMonitorGadget"), tr("Telemetry Monitor"), parent)
{}
MonitorGadgetFactory::~MonitorGadgetFactory()
{}
Core::IUAVGadget *MonitorGadgetFactory::createGadget(QWidget *parent)
{
MonitorWidget *widget = createMonitorWidget(parent);
return new MonitorGadget(QString("TelemetryMonitorGadget"), widget, parent);
}
MonitorWidget *MonitorGadgetFactory::createMonitorWidget(QWidget *parent)
{
MonitorWidget *widget = new MonitorWidget(parent);
// connect widget to telemetry manager
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
TelemetryManager *tm = pm->getObject<TelemetryManager>();
connect(tm, SIGNAL(connected()), widget, SLOT(telemetryConnected()));
connect(tm, SIGNAL(disconnected()), widget, SLOT(telemetryDisconnected()));
connect(tm, SIGNAL(telemetryUpdated(double, double)), widget, SLOT(telemetryUpdated(double, double)));
// and connect widget to connection manager (for retro compatibility)
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
connect(cm, SIGNAL(deviceConnected(QIODevice *)), widget, SLOT(telemetryConnected()));
connect(cm, SIGNAL(deviceDisconnected()), widget, SLOT(telemetryDisconnected()));
if (tm->isConnected()) {
widget->telemetryConnected();
}
return widget;
}
IUAVGadgetConfiguration *MonitorGadgetFactory::createConfiguration(QSettings *qSettings)
{
return new MonitorGadgetConfiguration(QString("TelemetryMonitorGadget"), qSettings);
}
IOptionsPage *MonitorGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
{
return new MonitorGadgetOptionsPage(qobject_cast<MonitorGadgetConfiguration *>(config));
}

View File

@ -0,0 +1,55 @@
/**
******************************************************************************
*
* @file monitorgadgetfactory.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup monitorgadget
* @{
*
*****************************************************************************/
/*
* 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 MONITORGADGETFACTORY_H
#define MONITORGADGETFACTORY_H
#include "monitorwidget.h"
#include <coreplugin/iuavgadgetfactory.h>
namespace Core {
class IUAVGadget;
class IUAVGadgetFactory;
}
using namespace Core;
class MonitorGadgetFactory : public IUAVGadgetFactory {
Q_OBJECT
public:
MonitorGadgetFactory(QObject *parent = 0);
~MonitorGadgetFactory();
Core::IUAVGadget *createGadget(QWidget *parent);
IUAVGadgetConfiguration *createConfiguration(QSettings *qSettings);
IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
MonitorWidget *createMonitorWidget(QWidget *parent);
};
#endif // MONITORGADGETFACTORY_H

View File

@ -0,0 +1,104 @@
/**
******************************************************************************
*
* @file monitorgadgetoptionspage.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Telemetry Gadget options page
* @see The GNU Public License (GPL) Version 3
* @defgroup monitorgadget
* @{
*
*****************************************************************************/
/*
* 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 "monitorgadgetoptionspage.h"
#include <coreplugin/icore.h>
// #include "ui_telemetrypluginoptionspage.h"
#include "extensionsystem/pluginmanager.h"
MonitorGadgetOptionsPage::MonitorGadgetOptionsPage(MonitorGadgetConfiguration *config, QObject *parent)
: IOptionsPage(parent)
{}
MonitorGadgetOptionsPage::~MonitorGadgetOptionsPage()
{}
QWidget *MonitorGadgetOptionsPage::createPage(QWidget * /* parent */)
{
// _optionsPage.reset(new Ui::TelemetryPluginOptionsPage());
//// main widget
// QWidget *optionsPageWidget = new QWidget;
// _dynamicFieldWidget = NULL;
// _dynamicFieldCondition = NULL;
// resetFieldType();
//// save ref to form, needed for binding dynamic fields in future
// _form = optionsPageWidget;
//// main layout
// _optionsPage->setupUi(optionsPageWidget);
//
// _optionsPage->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory);
// _optionsPage->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory"));
//
// connect(_optionsPage->SoundDirectoryPathChooser, SIGNAL(changed(const QString &)),
// this, SLOT(on_clicked_buttonSoundFolder(const QString &)));
// connect(_optionsPage->SoundCollectionList, SIGNAL(currentIndexChanged(int)),
// this, SLOT(on_changedIndex_soundLanguage(int)));
//
// connect(this, SIGNAL(updateNotifications(QList<NotificationItem *>)),
// _owner, SLOT(updateNotificationList(QList<NotificationItem *>)));
//// connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification()));
//
// _privListNotifications = _owner->getListNotifications();
//
//
//// [1]
// setSelectedNotification(_owner->getCurrentNotification());
// addDynamicFieldLayout();
//// [2]
// updateConfigView(_selectedNotification);
//
// initRulesTable();
// initButtons();
// initPhononPlayer();
//
// int curr_row = _privListNotifications.indexOf(_selectedNotification);
// _telemetryRulesSelection->setCurrentIndex(_telemetryRulesModel->index(curr_row, 0, QModelIndex()),
// QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
//
// return optionsPageWidget;
return NULL;
}
void MonitorGadgetOptionsPage::apply()
{
// getOptionsPageValues(_owner->getCurrentNotification());
// _owner->setEnableSound(_optionsPage->chkEnableSound->isChecked());
// emit updateNotifications(_privListNotifications);
}
void MonitorGadgetOptionsPage::finish()
{
// disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)),
// this, SLOT(on_changedIndex_UAVField(QString)));
//
// disconnect(_testSound.data(), SIGNAL(stateChanged(Phonon::State, Phonon::State)),
// this, SLOT(on_changed_playButtonText(Phonon::State, Phonon::State)));
// if (_testSound) {
// _testSound->stop();
// _testSound->clear();
// }
}

View File

@ -0,0 +1,61 @@
/**
******************************************************************************
*
* @file monitorgadgetoptionspage.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Telemetry Gadget options page header
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetry
* @{
*
*****************************************************************************/
/*
* 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 MONITORGADGETOPTIONSPAGE_H
#define MONITORGADGETOPTIONSPAGE_H
#include "coreplugin/dialogs/ioptionspage.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include "QString"
#include <QDebug>
#include <QtCore/QSettings>
namespace Ui {
class MonitorGadgetOptionsPage;
};
class MonitorGadgetConfiguration;
using namespace Core;
class MonitorGadgetOptionsPage : public IOptionsPage {
Q_OBJECT
public:
MonitorGadgetOptionsPage(MonitorGadgetConfiguration *config, QObject *parent = 0);
~MonitorGadgetOptionsPage();
QWidget *createPage(QWidget *parent);
void apply();
void finish();
private:
};
#endif // MONITORGADGETOPTIONSPAGE_H

View File

@ -0,0 +1,300 @@
#include "monitorwidget.h"
#include <utils/stylehelper.h>
#include <QObject>
#include <QDebug>
#include <QtGui/QFont>
namespace {
/**
* Create an SVG item and connect it to an element of the SVG file previously loaded into the parent item.
* This then allows to show, hide, move, scale and rotate the element.
* Opacity can also be changed.
* Other characteristics (color, ...) of the element cannot be modified.
*/
// TODO move to some utility class that can be reused by other SVG manipulating code
QGraphicsSvgItem *createSvgItem(QGraphicsSvgItem *parent, QString elementId)
{
QGraphicsSvgItem *item = new QGraphicsSvgItem(parent);
QSvgRenderer *renderer = parent->renderer();
// connect item to its corresponding element
item->setSharedRenderer(renderer);
item->setElementId(elementId);
// move item to its location
QMatrix elementMatrix = renderer->matrixForElement(elementId);
QRectF elementRect = elementMatrix.mapRect(renderer->boundsOnElement(elementId));
item->setPos(elementRect.x(), elementRect.y());
return item;
}
/**
* Create a text item based on a svg rectangle.
* The rectangle must be in the correct location (hint: use a "text" layer on top of the "background layer")
* The font size will be set to match as well as possible the rectangle height but it is not guaranteed.
*
* It is possible to show the text rectangle to help understand layout issues.
*
*/
// TODO move to some utility class that can be reused by other SVG manipulating code
QGraphicsTextItem *createTextItem(QGraphicsSvgItem *parent, QString elementId, QString fontName,
bool showRect = false)
{
if (showRect) {
// create and display the text rectangle
// needs to be done first otherwise the rectangle will blank out the text.
createSvgItem(parent, elementId);
}
QGraphicsTextItem *item = new QGraphicsTextItem();
QSvgRenderer *renderer = parent->renderer();
// move new text item to location of rectangle element
QMatrix elementMatrix = renderer->matrixForElement(elementId);
QRectF elementRect = elementMatrix.mapRect(renderer->boundsOnElement(elementId));
qreal fontPointSizeF = elementRect.height();
QTransform matrix;
matrix.translate(elementRect.x(), elementRect.y() - (fontPointSizeF / 2.0));
item->setParentItem(parent);
item->setTransform(matrix, false);
// to right align or center text we must provide a text width
// item->setTextWidth(elementRect.width());
// create font to match the rectangle height
// there is not guaranteed that all fonts will play well...
QFont font(fontName);
// not sure if PreferMatch helps to get the correct font size (i.e. that fits the text rectangle nicely)
font.setStyleStrategy(QFont::PreferMatch);
font.setPointSizeF(fontPointSizeF);
item->setFont(font);
#ifdef DEBUG_FONT
// just in case
qDebug() << "Font point size: " << fontPointSizeF;
qDebug() << "Font pixel size: " << font.pixelSize();
qDebug() << "Font point size: " << font.pointSize();
qDebug() << "Font point size F: " << font.pointSizeF();
qDebug() << "Font exact match: " << font.exactMatch();
QFontInfo fontInfo(font);
qDebug() << "Font info pixel size: " << fontInfo.pixelSize();
qDebug() << "Font info point size: " << fontInfo.pointSize();
qDebug() << "Font info point size F: " << fontInfo.pointSizeF();
qDebug() << "Font info exact match: " << fontInfo.exactMatch();
#endif
return item;
}
} // anonymous namespace
MonitorWidget::MonitorWidget(QWidget *parent) :
QGraphicsView(parent), aspectRatioMode(Qt::KeepAspectRatio)
{
// setMinimumWidth(180);
QGraphicsScene *scene = new QGraphicsScene();
setScene(scene);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
// no scroll bars
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor()));
setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
QSvgRenderer *renderer = new QSvgRenderer();
if (renderer->load(QString(":/telemetry/images/tx-rx.svg"))) {
// create graph
graph = new QGraphicsSvgItem();
graph->setSharedRenderer(renderer);
graph->setElementId("background");
graph->setFlags(QGraphicsItem::ItemClipsChildrenToShape | QGraphicsItem::ItemClipsToShape);
scene->addItem(graph);
int i;
// create tx nodes
i = 0;
while (true) {
QString id = QString("tx%0").arg(i);
QString bgId = QString("tx_bg%0").arg(i);
if (!renderer->elementExists(id) || !renderer->elementExists(bgId)) {
break;
}
QGraphicsSvgItem *item = createSvgItem(graph, bgId);
item->setElementId(id);
txNodes.append(item);
i++;
}
// create rx nodes
i = 0;
while (true) {
QString id = QString("rx%0").arg(i);
QString bgId = QString("rx_bg%0").arg(i);
if (!renderer->elementExists(id) || !renderer->elementExists(bgId)) {
break;
}
QGraphicsSvgItem *item = createSvgItem(graph, bgId);
item->setElementId(id);
rxNodes.append(item);
i++;
}
if (renderer->elementExists("txSpeed")) {
txSpeed = createTextItem(graph, "txSpeed", "Helvetica");
txSpeed->setDefaultTextColor(Qt::white);
} else {
txSpeed = NULL;
}
if (renderer->elementExists("rxSpeed")) {
rxSpeed = createTextItem(graph, "rxSpeed", "Helvetica");
rxSpeed->setDefaultTextColor(Qt::white);
} else {
rxSpeed = NULL;
}
// scene->setSceneRect(graph->boundingRect());
}
connected = false;
setMin(0.0);
setMax(1200.0);
telemetryUpdated(0.0, 0.0);
}
MonitorWidget::~MonitorWidget()
{
while (!txNodes.isEmpty()) {
delete txNodes.takeFirst();
}
while (!rxNodes.isEmpty()) {
delete rxNodes.takeFirst();
}
if (txSpeed) {
delete txSpeed;
}
if (rxSpeed) {
delete rxSpeed;
}
}
/*!
\brief Enables/Disables OpenGL
*/
// void LineardialGadgetWidget::enableOpenGL(bool flag)
// {
// if (flag) {
// setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
// } else {
// setViewport(new QWidget);
// }
// }
void MonitorWidget::telemetryConnected()
{
qDebug() << "telemetry connected";
if (!connected) {
// flash the lights
setToolTip(tr("Connected"));
telemetryUpdated(maxValue, maxValue);
connected = true;
}
}
void MonitorWidget::telemetryDisconnected()
{
qDebug() << "telemetry disconnected";
if (connected) {
connected = false;
setToolTip(tr("Disconnected"));
// flash the lights???
telemetryUpdated(maxValue, maxValue);
telemetryUpdated(0.0, 0.0);
}
}
/*!
\brief Called by the UAVObject which got updated
Updates the numeric value and/or the icon if the dial wants this.
*/
void MonitorWidget::telemetryUpdated(double txRate, double rxRate)
{
double txIndex = (txRate - minValue) / (maxValue - minValue) * txNodes.count();
double rxIndex = (rxRate - minValue) / (maxValue - minValue) * rxNodes.count();
if (connected) {
this->setToolTip(QString("Tx: %0 bytes/s, Rx: %1 bytes/s").arg(txRate).arg(rxRate));
}
for (int i = 0; i < txNodes.count(); i++) {
QGraphicsItem *node = txNodes.at(i);
bool visible = ( /*connected &&*/ (i < txIndex));
if (visible != node->isVisible()) {
node->setVisible(visible);
node->update();
}
}
for (int i = 0; i < rxNodes.count(); i++) {
QGraphicsItem *node = rxNodes.at(i);
bool visible = ( /*connected &&*/ (i < rxIndex));
if (visible != node->isVisible()) {
node->setVisible(visible);
node->update();
}
}
if (txSpeed) {
if (connected) {
txSpeed->setPlainText(QString("%0").arg(txRate));
}
txSpeed->setVisible(connected);
txSpeed->update();
}
if (rxSpeed) {
if (connected) {
rxSpeed->setPlainText(QString("%0").arg(rxRate));
}
rxSpeed->setVisible(connected);
rxSpeed->update();
}
update();
}
void MonitorWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event);
fitInView(graph, aspectRatioMode);
}
void MonitorWidget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
fitInView(graph, aspectRatioMode);
}

View File

@ -1,5 +1,5 @@
#ifndef TELEMETRYMONITORWIDGET_H
#define TELEMETRYMONITORWIDGET_H
#ifndef MONITORWIDGET_H
#define MONITORWIDGET_H
#include <QWidget>
#include <QObject>
@ -8,59 +8,56 @@
#include <QtSvg/QGraphicsSvgItem>
#include <QtCore/QPointer>
class TelemetryMonitorWidget : public QGraphicsView {
class MonitorWidget : public QGraphicsView {
Q_OBJECT
public:
explicit TelemetryMonitorWidget(QWidget *parent = 0);
~TelemetryMonitorWidget();
explicit MonitorWidget(QWidget *parent = 0);
~MonitorWidget();
void setMin(double min)
{
minValue = min;
}
double getMin()
{
return minValue;
}
void setMax(double max)
{
maxValue = max;
}
double getMax()
{
return maxValue;
}
// number of tx/rx nodes in the graph
static const int NODE_NUMELEM = 7;
signals:
public slots:
void connect();
void disconnect();
void updateTelemetry(double txRate, double rxRate);
void showTelemetry();
void telemetryConnected();
void telemetryDisconnected();
void telemetryUpdated(double txRate, double rxRate);
protected:
void showEvent(QShowEvent *event);
void resizeEvent(QResizeEvent *event);
private:
bool connected;
double minValue;
double maxValue;
QGraphicsSvgItem *graph;
QPointer<QGraphicsTextItem> txSpeed;
QPointer<QGraphicsTextItem> rxSpeed;
QList<QGraphicsSvgItem *> txNodes;
QList<QGraphicsSvgItem *> rxNodes;
bool connected;
double txIndex;
double txValue;
double rxIndex;
double rxValue;
double minValue;
double maxValue;
Qt::AspectRatioMode aspectRatioMode;
};
#endif // TELEMETRYMONITORWIDGET_H
#endif // MONITORWIDGET_H

View File

@ -0,0 +1,3 @@
include(telemetry_dependencies.pri)
LIBS *= -l$$qtLibraryName(Telemetry)

View File

@ -0,0 +1,29 @@
TEMPLATE = lib
TARGET = Telemetry
QT += svg
include(../../openpilotgcsplugin.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(telemetry_dependencies.pri)
HEADERS += telemetry_global.h \
telemetryplugin.h \
monitorwidget.h \
monitorgadgetconfiguration.h \
monitorgadget.h \
monitorgadgetfactory.h \
monitorgadgetoptionspage.h
SOURCES += telemetryplugin.cpp \
monitorwidget.cpp \
monitorgadgetconfiguration.cpp \
monitorgadget.cpp \
monitorgadgetfactory.cpp \
monitorgadgetoptionspage.cpp
DEFINES += TELEMETRY_LIBRARY
RESOURCES += telemetry.qrc
OTHER_FILES += Telemetry.pluginspec

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/telemetry">
<file>images/tx-rx.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,3 @@
include(../../plugins/uavtalk/uavtalk.pri)
include(../../plugins/uavobjects/uavobjects.pri)

View File

@ -0,0 +1,39 @@
/**
******************************************************************************
*
* @file telemetry_global.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup TelemetryPlugin Telemetry Plugin
* @{
* @brief The Telemetry plugin
*****************************************************************************/
/*
* 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 TELEMETRY_GLOBAL_H
#define TELEMETRY_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(TELEMETRY_LIBRARY)
# define TELEMETRY_EXPORT Q_DECL_EXPORT
#else
# define TELEMETRY_EXPORT Q_DECL_IMPORT
#endif
#endif // TELEMETRY_GLOBAL_H

View File

@ -0,0 +1,246 @@
/**
******************************************************************************
*
* @file telemetryplugin.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetryplugin
* @{
*
*****************************************************************************/
/*
* 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 "telemetryplugin.h"
#include "monitorgadgetfactory.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include "coreplugin/icore.h"
#include "coreplugin/connectionmanager.h"
#include <QDebug>
#include <QtPlugin>
#include <QStringList>
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/iuavgadget.h>
TelemetryPlugin::TelemetryPlugin()
{}
TelemetryPlugin::~TelemetryPlugin()
{
// Core::ICore::instance()->saveSettings(this);
}
bool TelemetryPlugin::initialize(const QStringList & args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
MonitorGadgetFactory *mf = new MonitorGadgetFactory(this);
addAutoReleasedObject(mf);
// mop = new TelemetryPluginOptionsPage(this);
// addAutoReleasedObject(mop);
// TODO not so good... g is probalby leaked...
MonitorWidget *w = mf->createMonitorWidget(NULL);
w->setMaximumWidth(180);
//
// setAlignment(Qt::AlignCenter);
// no border
w->setFrameStyle(QFrame::NoFrame);
w->setWindowFlags(Qt::FramelessWindowHint);
// set svg background translucent
w->setStyleSheet("background:transparent;");
// set widget background translucent
w->setAttribute(Qt::WA_TranslucentBackground);
w->setBackgroundBrush(Qt::NoBrush);
// add monitor widget to connection manager
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
// connect(cm, SIGNAL(deviceConnected(QIODevice *)), w, SLOT(telemetryConnected()));
// connect(cm, SIGNAL(deviceDisconnected()), w, SLOT(telemetryDisconnected()));
cm->addWidget(w);
return true;
}
void TelemetryPlugin::extensionsInitialized()
{
// Core::ICore::instance()->readSettings(this);
// ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
// connect(pm, SIGNAL(objectAdded(QObject *)), this, SLOT(onTelemetryManagerAdded(QObject *)));
// _toRemoveNotifications.clear();
// connectNotifications();
}
// void TelemetryPlugin::saveConfig(QSettings *settings, UAVConfigInfo *configInfo)
// {
// configInfo->setVersion(VERSION);
//
// settings->beginWriteArray("Current");
// settings->setArrayIndex(0);
// currentNotification.saveState(settings);
// settings->endArray();
//
// settings->beginGroup("listNotifies");
// settings->remove("");
// settings->endGroup();
//
// settings->beginWriteArray("listNotifies");
// for (int i = 0; i < _notificationList.size(); i++) {
// settings->setArrayIndex(i);
// _notificationList.at(i)->saveState(settings);
// }
// settings->endArray();
// settings->setValue(QLatin1String("Enable"), enable);
// }
// void TelemetryPlugin::readConfig(QSettings *settings, UAVConfigInfo * /* configInfo */)
// {
//// Just for migration to the new format.
//// Q_ASSERT(configInfo->version() == UAVConfigVersion());
//
// settings->beginReadArray("Current");
// settings->setArrayIndex(0);
// currentNotification.restoreState(settings);
// settings->endArray();
//
//// read list of notifications from settings
// int size = settings->beginReadArray("listNotifies");
// for (int i = 0; i < size; ++i) {
// settings->setArrayIndex(i);
// NotificationItem *notification = new NotificationItem;
// notification->restoreState(settings);
// _notificationList.append(notification);
// }
// settings->endArray();
// setEnable(settings->value(QLatin1String("Enable"), 0).toBool());
// }
// void TelemetryPlugin::onTelemetryManagerAdded(QObject *obj)
// {
// telMngr = qobject_cast<TelemetryManager *>(obj);
// if (telMngr) {
// connect(telMngr, SIGNAL(disconnected()), this, SLOT(onAutopilotDisconnect()));
// }
// }
void TelemetryPlugin::shutdown()
{
// Do nothing
}
// void TelemetryPlugin::onAutopilotDisconnect()
// {
// connectNotifications();
// }
///*!
// clear any telemetry timers from previous flight;
// reset will be perform on start of option page
// */
// void TelemetryPlugin::resetNotification(void)
// {
//// first, reject empty args and unknown fields.
// foreach(NotificationItem * ntf, _notificationList) {
// ntf->disposeTimer();
// disconnect(ntf->getTimer(), SIGNAL(timeout()), this, SLOT(on_timerRepeated_Notification()));
// ntf->disposeExpireTimer();
// disconnect(ntf->getExpireTimer(), SIGNAL(timeout()), this, SLOT(on_timerRepeated_Notification()));
// }
// }
// void TelemetryPlugin::connectNotifications()
// {
// foreach(UAVDataObject * obj, lstNotifiedUAVObjects) {
// if (obj != NULL) {
// disconnect(obj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(on_arrived_Notification(UAVObject *)));
// }
// }
// if (phonon.mo != NULL) {
// delete phonon.mo;
// phonon.mo = NULL;
// }
//
// if (!enable) {
// return;
// }
//
// ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
// UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
//
// lstNotifiedUAVObjects.clear();
// _pendingNotifications.clear();
// _notificationList.append(_toRemoveNotifications);
// _toRemoveNotifications.clear();
//
//// first, reject empty args and unknown fields.
// foreach(NotificationItem * telemetry, _notificationList) {
// telemetry->_isPlayed = false;
// telemetry->isNowPlaying = false;
//
// if (telemetry->mute()) {
// continue;
// }
//// check is all sounds presented for notification,
//// if not - we must not subscribe to it at all
// if (telemetry->toList().isEmpty()) {
// continue;
// }
//
// UAVDataObject *obj = dynamic_cast<UAVDataObject *>(objManager->getObject(telemetry->getDataObject()));
// if (obj != NULL) {
// if (!lstNotifiedUAVObjects.contains(obj)) {
// lstNotifiedUAVObjects.append(obj);
//
// connect(obj, SIGNAL(objectUpdated(UAVObject *)),
// this, SLOT(on_arrived_Notification(UAVObject *)),
// Qt::QueuedConnection);
// }
// } else {
// qTelemetryDebug() << "Error: Object is unknown (" << telemetry->getDataObject() << ").";
// }
// }
//
// if (_notificationList.isEmpty()) {
// return;
// }
//// set notification message to current event
// phonon.mo = Phonon::createPlayer(Phonon::NotificationCategory);
// phonon.mo->clearQueue();
// phonon.firstPlay = true;
// QList<Phonon::AudioOutputDevice> audioOutputDevices =
// Phonon::BackendCapabilities::availableAudioOutputDevices();
// foreach(Phonon::AudioOutputDevice dev, audioOutputDevices) {
// qTelemetryDebug() << "Telemetry: Audio Output device: " << dev.name() << " - " << dev.description();
// }
// connect(phonon.mo, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
// this, SLOT(stateChanged(Phonon::State, Phonon::State)));
// }

View File

@ -0,0 +1,51 @@
/**
******************************************************************************
*
* @file telemetryplugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup telemetryplugin
* @{
*
*****************************************************************************/
/*
* 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 TELEMETRYPLUGIN_H
#define TELEMETRYPLUGIN_H
#include <extensionsystem/iplugin.h>
class MonitorGadgetFactory;
class TelemetryPlugin : public ExtensionSystem::IPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID "OpenPilot.Telemetry")
public:
TelemetryPlugin();
~TelemetryPlugin();
void extensionsInitialized();
bool initialize(const QStringList &arguments, QString *errorString);
void shutdown();
private:
MonitorGadgetFactory *mf;
};
#endif // TELEMETRYPLUGIN_H

View File

@ -0,0 +1,100 @@
/**
******************************************************************************
*
* @file uavobjecthelper.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup UAVObjectHelper
* @{
* @brief [Brief]
*****************************************************************************/
/*
* 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 "uavobjecthelper.h"
#include <QTimer>
AbstractUAVObjectHelper::AbstractUAVObjectHelper(QObject *parent) :
QObject(parent), m_transactionResult(false), m_transactionCompleted(false)
{}
AbstractUAVObjectHelper::Result AbstractUAVObjectHelper::doObjectAndWait(UAVObject *object, int timeout)
{
// Lock, we can't call this twice from different threads
QMutexLocker locker(&m_mutex);
m_object = object;
// Reset variables
m_transactionResult = false;
m_transactionCompleted = false;
// Create timer and connect it, connect object tx completed to local slot
QTimer timeoutTimer;
timeoutTimer.setSingleShot(true);
connect(&timeoutTimer, SIGNAL(timeout()), &m_eventLoop, SLOT(quit()));
connect(object, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(transactionCompleted(UAVObject *, bool)));
// Start timeout timer
timeoutTimer.start(timeout);
// Call the actual implementation in concrete subclass
doObjectAndWaitImpl();
// Wait if not completed
if (!m_transactionCompleted) {
m_eventLoop.exec();
}
timeoutTimer.stop();
// Disconnect
disconnect(object, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(transactionCompleted(UAVObject *, bool)));
disconnect(&timeoutTimer, SIGNAL(timeout()), &m_eventLoop, SLOT(quit()));
// Return result
if (!m_transactionCompleted) {
return TIMEOUT;
} else {
return m_transactionResult ? SUCCESS : FAIL;
}
}
void AbstractUAVObjectHelper::transactionCompleted(UAVObject *object, bool success)
{
Q_UNUSED(object)
// Set variables and quit event loop
m_transactionResult = success;
m_transactionCompleted = true;
m_eventLoop.quit();
}
UAVObjectUpdaterHelper::UAVObjectUpdaterHelper(QObject *parent) : AbstractUAVObjectHelper(parent)
{}
void UAVObjectUpdaterHelper::doObjectAndWaitImpl()
{
m_object->updated();
}
UAVObjectRequestHelper::UAVObjectRequestHelper(QObject *parent) : AbstractUAVObjectHelper(parent)
{}
void UAVObjectRequestHelper::doObjectAndWaitImpl()
{
m_object->requestUpdate();
}

View File

@ -0,0 +1,78 @@
/**
******************************************************************************
*
* @file uavobjecthelper.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup [Group]
* @{
* @addtogroup UAVObjectHelper
* @{
* @brief [Brief]
*****************************************************************************/
/*
* 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 UAVOBJECTHELPER_H
#define UAVOBJECTHELPER_H
#include <QObject>
#include <QEventLoop>
#include <QMutex>
#include <QMutexLocker>
#include "uavobject.h"
class UAVOBJECTS_EXPORT AbstractUAVObjectHelper : public QObject {
Q_OBJECT
public:
explicit AbstractUAVObjectHelper(QObject *parent = 0);
enum Result { SUCCESS, FAIL, TIMEOUT };
Result doObjectAndWait(UAVObject *object, int timeout);
protected:
virtual void doObjectAndWaitImpl() = 0;
UAVObject *m_object;
private slots:
void transactionCompleted(UAVObject *object, bool success);
private:
QMutex m_mutex;
QEventLoop m_eventLoop;
bool m_transactionResult;
bool m_transactionCompleted;
};
class UAVOBJECTS_EXPORT UAVObjectUpdaterHelper : public AbstractUAVObjectHelper {
Q_OBJECT
public:
explicit UAVObjectUpdaterHelper(QObject *parent = 0);
protected:
virtual void doObjectAndWaitImpl();
};
class UAVOBJECTS_EXPORT UAVObjectRequestHelper : public AbstractUAVObjectHelper {
Q_OBJECT
public:
explicit UAVObjectRequestHelper(QObject *parent = 0);
protected:
virtual void doObjectAndWaitImpl();
};
#endif // UAVOBJECTHELPER_H

View File

@ -11,14 +11,16 @@ HEADERS += uavobjects_global.h \
uavdataobject.h \
uavobjectfield.h \
uavobjectsinit.h \
uavobjectsplugin.h
uavobjectsplugin.h \
uavobjecthelper.h
SOURCES += uavobject.cpp \
uavmetaobject.cpp \
uavobjectmanager.cpp \
uavdataobject.cpp \
uavobjectfield.cpp \
uavobjectsplugin.cpp
uavobjectsplugin.cpp \
uavobjecthelper.cpp
OTHER_FILES += UAVObjects.pluginspec

View File

@ -64,9 +64,9 @@ void TelemetryManager::onStart()
telemetryMon = new TelemetryMonitor(objMngr, telemetry);
connect(telemetryMon, SIGNAL(connected()), this, SLOT(onConnect()));
connect(telemetryMon, SIGNAL(disconnected()), this, SLOT(onDisconnect()));
connect(telemetryMon, SIGNAL(telemetryUpdated(double, double)), this, SLOT(onTelemetryUpdate(double, double)));
}
void TelemetryManager::stop()
{
emit myStop();
@ -92,3 +92,8 @@ void TelemetryManager::onDisconnect()
autopilotConnected = false;
emit disconnected();
}
void TelemetryManager::onTelemetryUpdate(double txRate, double rxRate)
{
emit telemetryUpdated(txRate, rxRate);
}

View File

@ -50,12 +50,14 @@ public:
signals:
void connected();
void disconnected();
void telemetryUpdated(double txRate, double rxRate);
void myStart();
void myStop();
private slots:
void onConnect();
void onDisconnect();
void onTelemetryUpdate(double txRate, double rxRate);
void onStart();
void onStop();

View File

@ -49,11 +49,6 @@ TelemetryMonitor::TelemetryMonitor(UAVObjectManager *objMngr, Telemetry *tel) :
// Start update timer
connect(statsTimer, SIGNAL(timeout()), this, SLOT(processStatsUpdates()));
statsTimer->start(STATS_CONNECT_PERIOD_MS);
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
connect(this, SIGNAL(connected()), cm, SLOT(telemetryConnected()));
connect(this, SIGNAL(disconnected()), cm, SLOT(telemetryDisconnected()));
connect(this, SIGNAL(telemetryUpdated(double, double)), cm, SLOT(telemetryUpdated(double, double)));
}
TelemetryMonitor::~TelemetryMonitor()

View File

@ -1,18 +1,24 @@
QT += network
TEMPLATE = lib
TARGET = UAVTalk
QT += network
include(../../openpilotgcsplugin.pri)
include(uavtalk_dependencies.pri)
HEADERS += uavtalk.h \
uavtalkplugin.h \
telemetrymonitor.h \
telemetrymanager.h \
uavtalk_global.h \
telemetry.h
SOURCES += uavtalk.cpp \
uavtalkplugin.cpp \
telemetrymonitor.cpp \
telemetrymanager.cpp \
telemetry.cpp
DEFINES += UAVTALK_LIBRARY
OTHER_FILES += UAVTalk.pluginspec