mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-20 10:54:14 +01:00
Merge branch 'thread/OP-1119_Flight_Side_Logs_Plugin' into next
This commit is contained in:
commit
1d6df555eb
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
||||
|
@ -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>
|
189
ground/openpilotgcs/src/plugins/flightlog/FlightLogDialog.qml
Normal file
189
ground/openpilotgcs/src/plugins/flightlog/FlightLogDialog.qml
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
ground/openpilotgcs/src/plugins/flightlog/flightLog.qrc
Normal file
6
ground/openpilotgcs/src/plugins/flightlog/flightLog.qrc
Normal file
@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/flightlog">
|
||||
<file>FlightLogDialog.qml</file>
|
||||
<file>functions.js</file>
|
||||
</qresource>
|
||||
</RCC>
|
25
ground/openpilotgcs/src/plugins/flightlog/flightlog.pro
Normal file
25
ground/openpilotgcs/src/plugins/flightlog/flightlog.pro
Normal 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
|
@ -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()
|
||||
{}
|
15
ground/openpilotgcs/src/plugins/flightlog/flightlogdialog.h
Normal file
15
ground/openpilotgcs/src/plugins/flightlog/flightlogdialog.h
Normal 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
|
311
ground/openpilotgcs/src/plugins/flightlog/flightlogmanager.cpp
Normal file
311
ground/openpilotgcs/src/plugins/flightlog/flightlogmanager.cpp
Normal 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);
|
||||
}
|
||||
}
|
162
ground/openpilotgcs/src/plugins/flightlog/flightlogmanager.h
Normal file
162
ground/openpilotgcs/src/plugins/flightlog/flightlogmanager.h
Normal 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
|
@ -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();
|
||||
}
|
||||
}
|
53
ground/openpilotgcs/src/plugins/flightlog/flightlogplugin.h
Normal file
53
ground/openpilotgcs/src/plugins/flightlog/flightlogplugin.h
Normal 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_ */
|
20
ground/openpilotgcs/src/plugins/flightlog/functions.js
Normal file
20
ground/openpilotgcs/src/plugins/flightlog/functions.js
Normal 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;
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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>
|
||||
|
@ -244,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
|
||||
|
||||
|
100
ground/openpilotgcs/src/plugins/uavobjects/uavobjecthelper.cpp
Normal file
100
ground/openpilotgcs/src/plugins/uavobjects/uavobjecthelper.cpp
Normal 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();
|
||||
}
|
78
ground/openpilotgcs/src/plugins/uavobjects/uavobjecthelper.h
Normal file
78
ground/openpilotgcs/src/plugins/uavobjects/uavobjecthelper.h
Normal 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
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user