1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-19 04:52:12 +01:00

Merge branch 'thread/OP-1777_Usage_statistics' into next

This commit is contained in:
m_thread 2015-04-17 08:26:02 +02:00
commit ddb2025108
8 changed files with 563 additions and 89 deletions

View File

@ -49,6 +49,8 @@ GeneralSettings::GeneralSettings() :
m_autoSelect(true), m_autoSelect(true),
m_useUDPMirror(false), m_useUDPMirror(false),
m_useExpertMode(false), m_useExpertMode(false),
m_collectUsageData(true),
m_showUsageDataDisclaimer(true),
m_dialog(0) m_dialog(0)
{} {}
@ -125,6 +127,7 @@ QWidget *GeneralSettings::createPage(QWidget *parent)
m_page->checkAutoSelect->setChecked(m_autoSelect); m_page->checkAutoSelect->setChecked(m_autoSelect);
m_page->cbUseUDPMirror->setChecked(m_useUDPMirror); m_page->cbUseUDPMirror->setChecked(m_useUDPMirror);
m_page->cbExpertMode->setChecked(m_useExpertMode); m_page->cbExpertMode->setChecked(m_useExpertMode);
m_page->cbUsageData->setChecked(m_collectUsageData);
m_page->colorButton->setColor(StyleHelper::baseColor()); m_page->colorButton->setColor(StyleHelper::baseColor());
connect(m_page->resetButton, SIGNAL(clicked()), this, SLOT(resetInterfaceColor())); connect(m_page->resetButton, SIGNAL(clicked()), this, SLOT(resetInterfaceColor()));
@ -145,6 +148,7 @@ void GeneralSettings::apply()
m_useExpertMode = m_page->cbExpertMode->isChecked(); m_useExpertMode = m_page->cbExpertMode->isChecked();
m_autoConnect = m_page->checkAutoConnect->isChecked(); m_autoConnect = m_page->checkAutoConnect->isChecked();
m_autoSelect = m_page->checkAutoSelect->isChecked(); m_autoSelect = m_page->checkAutoSelect->isChecked();
setCollectUsageData(m_page->cbUsageData->isChecked());
} }
void GeneralSettings::finish() void GeneralSettings::finish()
@ -161,6 +165,9 @@ void GeneralSettings::readSettings(QSettings *qs)
m_autoSelect = qs->value(QLatin1String("AutoSelect"), m_autoSelect).toBool(); m_autoSelect = qs->value(QLatin1String("AutoSelect"), m_autoSelect).toBool();
m_useUDPMirror = qs->value(QLatin1String("UDPMirror"), m_useUDPMirror).toBool(); m_useUDPMirror = qs->value(QLatin1String("UDPMirror"), m_useUDPMirror).toBool();
m_useExpertMode = qs->value(QLatin1String("ExpertMode"), m_useExpertMode).toBool(); m_useExpertMode = qs->value(QLatin1String("ExpertMode"), m_useExpertMode).toBool();
m_collectUsageData = qs->value(QLatin1String("CollectUsageData"), m_collectUsageData).toBool();
m_showUsageDataDisclaimer = qs->value(QLatin1String("ShowUsageDataDisclaimer"), m_showUsageDataDisclaimer).toBool();
m_lastUsageHash = qs->value(QLatin1String("LastUsageHash"), m_lastUsageHash).toString();
qs->endGroup(); qs->endGroup();
} }
@ -179,6 +186,9 @@ void GeneralSettings::saveSettings(QSettings *qs)
qs->setValue(QLatin1String("AutoSelect"), m_autoSelect); qs->setValue(QLatin1String("AutoSelect"), m_autoSelect);
qs->setValue(QLatin1String("UDPMirror"), m_useUDPMirror); qs->setValue(QLatin1String("UDPMirror"), m_useUDPMirror);
qs->setValue(QLatin1String("ExpertMode"), m_useExpertMode); qs->setValue(QLatin1String("ExpertMode"), m_useExpertMode);
qs->setValue(QLatin1String("CollectUsageData"), m_collectUsageData);
qs->setValue(QLatin1String("ShowUsageDataDisclaimer"), m_showUsageDataDisclaimer);
qs->setValue(QLatin1String("LastUsageHash"), m_lastUsageHash);
qs->endGroup(); qs->endGroup();
} }
@ -249,11 +259,44 @@ bool GeneralSettings::useUDPMirror() const
return m_useUDPMirror; return m_useUDPMirror;
} }
bool GeneralSettings::collectUsageData() const
{
return m_collectUsageData;
}
bool GeneralSettings::showUsageDataDisclaimer() const
{
return m_showUsageDataDisclaimer;
}
QString GeneralSettings::lastUsageHash() const
{
return m_lastUsageHash;
}
bool GeneralSettings::useExpertMode() const bool GeneralSettings::useExpertMode() const
{ {
return m_useExpertMode; return m_useExpertMode;
} }
bool GeneralSettings::setCollectUsageData(bool collect)
{
if (collect && collect != m_collectUsageData) {
setShowUsageDataDisclaimer(true);
}
m_collectUsageData = collect;
}
bool GeneralSettings::setShowUsageDataDisclaimer(bool show)
{
m_showUsageDataDisclaimer = show;
}
void GeneralSettings::setLastUsageHash(QString hash)
{
m_lastUsageHash = hash;
}
void GeneralSettings::slotAutoConnect(int value) void GeneralSettings::slotAutoConnect(int value)
{ {
if (value == Qt::Checked) { if (value == Qt::Checked) {

View File

@ -57,10 +57,15 @@ public:
bool autoConnect() const; bool autoConnect() const;
bool autoSelect() const; bool autoSelect() const;
bool useUDPMirror() const; bool useUDPMirror() const;
bool collectUsageData() const;
bool showUsageDataDisclaimer() const;
QString lastUsageHash() const;
void readSettings(QSettings *qs); void readSettings(QSettings *qs);
void saveSettings(QSettings *qs); void saveSettings(QSettings *qs);
bool useExpertMode() const; bool useExpertMode() const;
signals: bool setCollectUsageData(bool collect);
bool setShowUsageDataDisclaimer(bool show);
void setLastUsageHash(QString hash);
private slots: private slots:
void resetInterfaceColor(); void resetInterfaceColor();
@ -79,6 +84,9 @@ private:
bool m_autoSelect; bool m_autoSelect;
bool m_useUDPMirror; bool m_useUDPMirror;
bool m_useExpertMode; bool m_useExpertMode;
bool m_collectUsageData;
bool m_showUsageDataDisclaimer;
QString m_lastUsageHash;
QPointer<QWidget> m_dialog; QPointer<QWidget> m_dialog;
QList<QTextCodec *> m_codecs; QList<QTextCodec *> m_codecs;
}; };

View File

@ -11,7 +11,16 @@
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="margin"> <property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
@ -20,17 +29,73 @@
<string>General settings</string> <string>General settings</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="0"> <item row="0" column="0">
<widget class="QLabel" name="colorLabel"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>User interface color:</string> <string>Language:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="14" column="0">
<widget class="QLabel" name="labelExpert">
<property name="text">
<string>Expert Mode:</string>
</property>
</widget>
</item>
<item row="13" column="2">
<widget class="QCheckBox" name="cbUseUDPMirror">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="12" column="2">
<widget class="QCheckBox" name="checkAutoSelect">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Automatically connect an OpenPilot USB device:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QCheckBox" name="checkBoxSaveOnExit">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QWidget" name="widget" native="true"> <widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<property name="margin"> <property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item row="0" column="1"> <item row="0" column="1">
@ -82,46 +147,46 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="9" column="1"> <item row="1" column="0">
<widget class="QLabel" name="colorLabel">
<property name="text">
<string>User interface color:</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="labelExpert_2">
<property name="text">
<string>Contribute usage statistics:</string>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QWidget" name="widget_2" native="true"> <widget class="QWidget" name="widget_2" native="true">
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<property name="margin"> <property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="10" column="1"> <item row="14" column="2">
<widget class="QCheckBox" name="checkBoxSaveOnExit"> <widget class="QCheckBox" name="cbExpertMode">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="checked">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item row="10" column="0"> <item row="11" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Save configuration settings on exit:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Automatically connect an OpenPilot USB device:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QCheckBox" name="checkAutoConnect"> <widget class="QCheckBox" name="checkAutoConnect">
<property name="text"> <property name="text">
<string/> <string/>
@ -131,58 +196,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="12" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Automatically select an OpenPilot USB device:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QCheckBox" name="checkAutoSelect">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QCheckBox" name="cbUseUDPMirror">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="13" column="0"> <item row="13" column="0">
<widget class="QLabel" name="labelUDP"> <widget class="QLabel" name="labelUDP">
<property name="text"> <property name="text">
<string>Use UDP Mirror</string> <string>Use UDP Mirror:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="14" column="0"> <item row="0" column="2">
<widget class="QLabel" name="labelExpert">
<property name="text">
<string>Expert Mode</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QCheckBox" name="cbExpertMode">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QComboBox" name="languageBox"/> <widget class="QComboBox" name="languageBox"/>
@ -202,10 +223,33 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="0" column="0"> <item row="10" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>Language:</string> <string>Save configuration settings on exit:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Automatically select an OpenPilot USB device:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="15" column="2">
<widget class="QCheckBox" name="cbUsageData">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -252,3 +252,11 @@ plugin_flightlog.depends += plugin_uavobjects
plugin_flightlog.depends += plugin_uavtalk plugin_flightlog.depends += plugin_uavtalk
SUBDIRS += plugin_flightlog SUBDIRS += plugin_flightlog
# Usage Tracker plugin
plugin_usagetracker.subdir = usagetracker
plugin_usagetracker.depends = plugin_coreplugin
plugin_usagetracker.depends += plugin_uavobjects
plugin_usagetracker.depends += plugin_uavtalk
plugin_setupwizard.depends += plugin_uavobjectutil
SUBDIRS += plugin_usagetracker

View File

@ -0,0 +1,12 @@
<plugin name="UsageTracker" version="1.0.0" compatVersion="1.0.0">
<vendor>The OpenPilot Project</vendor>
<copyright>(C) 2015 OpenPilot Project</copyright>
<description>A plugin that tracks GCS usage</description>
<url>http://www.openpilot.org</url>
<dependencyList>
<dependency name="Core" version="1.0.0"/>
<dependency name="UAVTalk" version="1.0.0"/>
<dependency name="UAVObjectUtil" version="1.0.0"/>
<dependency name="UAVObjects" version="1.0.0"/>
</dependencyList>
</plugin>

View File

@ -0,0 +1,16 @@
TEMPLATE = lib
TARGET = UsageTracker
QT += network
include(../../openpilotgcsplugin.pri)
include(../../libs/version_info/version_info.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/uavobjects/uavobjects.pri)
include(../../plugins/uavobjectutil/uavobjectutil.pri)
include(../../plugins/uavtalk/uavtalk.pri)
HEADERS += usagetrackerplugin.h
SOURCES += usagetrackerplugin.cpp
OTHER_FILES += usagetracker.pluginspec

View File

@ -0,0 +1,280 @@
/**
******************************************************************************
*
* @file usagetrackerplugin.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup UsageTrackerPlugin Usage Tracker Plugin
* @{
* @brief A plugin tracking GCS usage
*****************************************************************************/
/*
* 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 "usagetrackerplugin.h"
#include <QtPlugin>
#include <QStringList>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <extensionsystem/pluginmanager.h>
#include <QCheckBox>
#include <QDebug>
#include <QMessageBox>
#include <uavobjectutil/devicedescriptorstruct.h>
#include <uavobjectutil/uavobjectutilmanager.h>
#include "version_info/version_info.h"
#include "coreplugin/icore.h"
#include <uavtalk/telemetrymanager.h>
UsageTrackerPlugin::UsageTrackerPlugin() :
m_telemetryManager(NULL)
{}
UsageTrackerPlugin::~UsageTrackerPlugin()
{}
bool UsageTrackerPlugin::initialize(const QStringList & args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
return true;
}
void UsageTrackerPlugin::extensionsInitialized()
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
m_telemetryManager = pm->getObject<TelemetryManager>();
connect(m_telemetryManager, SIGNAL(connected()), this, SLOT(onAutopilotConnect()));
}
void UsageTrackerPlugin::shutdown()
{
if (m_telemetryManager != NULL) {
disconnect(m_telemetryManager, SIGNAL(connected()), this, SLOT(onAutopilotConnect()));
}
}
void UsageTrackerPlugin::onAutopilotConnect()
{
Core::Internal::GeneralSettings *settings = getGeneralSettings();
if (settings->collectUsageData()) {
if (settings->showUsageDataDisclaimer()) {
QMessageBox message;
message.setWindowTitle(tr("Usage feedback"));
message.setIcon(QMessageBox::Information);
message.addButton(tr("Yes, count me in"), QMessageBox::AcceptRole);
message.addButton(tr("No, I will not help"), QMessageBox::RejectRole);
message.setText(tr("Openpilot GCS has a function to collect limited anonymous information about "
"the usage of the application itself and the OpenPilot hardware connected to it.<p>"
"The intention is to not include anything that can be considered sensitive "
"or a threat to the users integrity. The collected information will be sent "
"using a secure protocol to an OpenPilot web service and stored in a database "
"for later analysis and statistical purposes.<br>"
"No information will be sold or given to any third party. The sole purpose is "
"to collect statistics about the usage of our software and hardware to enable us "
"to make things better for you.<p>"
"The following things are collected:<ul>"
"<li>Bootloader version</li>"
"<li>Firmware version, tag and git hash</li>"
"<li>OP Hardware type, revision and mcu serial number</li>"
"<li>Selected configuration parameters</li>"
"<li>GCS version</li>"
"<li>Operating system version and architecture</li>"
"<li>Current local time</li></ul>"
"The information is collected only at the time when a board is connecting to GCS.<p>"
"It is possible to enable or disable this functionality in the general "
"settings part of the options for the GCS application at any time.<p>"
"We need your help, with your feedback we know where to improve things and what "
"platforms are in use. This is a community project that depends on people being involved.<br>"
"Thank You for helping us making things better and for supporting OpenPilot!"));
QCheckBox *disclaimerCb = new QCheckBox(tr("&Don't show this message again."));
disclaimerCb->setChecked(true);
message.setCheckBox(disclaimerCb);
if (message.exec() != QMessageBox::AcceptRole) {
settings->setCollectUsageData(false);
settings->setShowUsageDataDisclaimer(!message.checkBox()->isChecked());
return;
} else {
settings->setCollectUsageData(true);
settings->setShowUsageDataDisclaimer(!message.checkBox()->isChecked());
}
}
QTimer::singleShot(1000, this, SLOT(trackUsage()));
}
}
void UsageTrackerPlugin::trackUsage()
{
QMap<QString, QString> parameters;
collectUsageParameters(parameters);
QUrlQuery query;
QMapIterator<QString, QString> iter(parameters);
while (iter.hasNext()) {
iter.next();
query.addQueryItem(iter.key(), iter.value());
}
// Add checksum
QString hash = getQueryHash(query.toString());
if (shouldSend(hash)) {
query.addQueryItem("hash", hash);
QUrl url("https://www.openpilot.org/opver?" + query.toString(QUrl::FullyEncoded));
QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager();
// This will delete the network access manager instance when we're done
connect(networkAccessManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(onFinished(QNetworkReply *)));
connect(networkAccessManager, SIGNAL(finished(QNetworkReply *)), networkAccessManager, SLOT(deleteLater()));
qDebug() << "Sending usage tracking as:" << url.toEncoded(QUrl::FullyEncoded);
networkAccessManager->get(QNetworkRequest(QUrl(url.toEncoded(QUrl::FullyEncoded))));
}
}
void UsageTrackerPlugin::collectUsageParameters(QMap<QString, QString> &parameters)
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectUtilManager *utilMngr = pm->getObject<UAVObjectUtilManager>();
QByteArray description = utilMngr->getBoardDescription();
deviceDescriptorStruct devDesc;
if (UAVObjectUtilManager::descriptionToStructure(description, devDesc)) {
int boardModel = utilMngr->getBoardModel();
parameters["board_type"] = "0x" + QString::number(boardModel, 16).toLower();
parameters["board_serial"] = utilMngr->getBoardCPUSerial().toHex();
parameters["bl_version"] = QString::number(utilMngr->getBootloaderRevision());
parameters["fw_tag"] = devDesc.gitTag;
parameters["fw_hash"] = devDesc.gitHash;
parameters["os_version"] = QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture();
parameters["os_threads"] = QString::number(QThread::idealThreadCount());
parameters["os_timezone"] = QTimeZone::systemTimeZoneId();
parameters["gcs_version"] = VersionInfo::revision();
// Configuration parameters
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
parameters["conf_receiver"] = getUAVFieldValue(objManager, "ManualControlSettings", "ChannelGroups", 0);
parameters["conf_vehicle"] = getUAVFieldValue(objManager, "SystemSettings", "AirframeType");
if ((boardModel & 0xff00) == 0x0400) {
// CopterControl family
parameters["conf_rport"] = getUAVFieldValue(objManager, "HwSettings", "CC_RcvrPort");
parameters["conf_mport"] = getUAVFieldValue(objManager, "HwSettings", "CC_MainPort");
parameters["conf_fport"] = getUAVFieldValue(objManager, "HwSettings", "CC_FlexiPort");
} else if ((boardModel & 0xff00) == 0x0900) {
// Revolution family
parameters["conf_rport"] = getUAVFieldValue(objManager, "HwSettings", "RM_RcvrPort");
parameters["conf_mport"] = getUAVFieldValue(objManager, "HwSettings", "RM_MainPort");
parameters["conf_fport"] = getUAVFieldValue(objManager, "HwSettings", "RM_FlexiPort");
parameters["conf_fusion"] = getUAVFieldValue(objManager, "RevoSettings", "FusionAlgorithm");
}
parameters["conf_uport"] = getUAVFieldValue(objManager, "HwSettings", "USB_HIDPort");
parameters["conf_vport"] = getUAVFieldValue(objManager, "HwSettings", "USB_VCPPort");
parameters["conf_rotation"] = QString("[%1:%2:%3]")
.arg(getUAVFieldValue(objManager, "AttitudeSettings", "BoardRotation", 0))
.arg(getUAVFieldValue(objManager, "AttitudeSettings", "BoardRotation", 1))
.arg(getUAVFieldValue(objManager, "AttitudeSettings", "BoardRotation", 2));
parameters["conf_pidr"] = QString("[%1:%2:%3:%4][%5:%6:%7:%8][%9:%10:%11:%12]")
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollRatePID", 0))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollRatePID", 1))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollRatePID", 2))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollRatePID", 3))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchRatePID", 0))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchRatePID", 1))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchRatePID", 2))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchRatePID", 3))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawRatePID", 0))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawRatePID", 1))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawRatePID", 2))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawRatePID", 3));
parameters["conf_pia"] = QString("[%1:%2:%3][%4:%5:%6][%7:%8:%9]")
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollPI", 0))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollPI", 1))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollPI", 2))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchPI", 0))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchPI", 1))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchPI", 2))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawPI", 0))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawPI", 1))
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawPI", 2));
parameters["conf_tps"] = getUAVFieldValue(objManager, "StabilizationSettingsBank1", "EnableThrustPIDScaling");
parameters["conf_piro"] = getUAVFieldValue(objManager, "StabilizationSettingsBank1", "EnablePiroComp");
parameters["conf_fmcount"] = getUAVFieldValue(objManager, "ManualControlSettings", "FlightModeNumber");
parameters["conf_fmodes"] = QString("[%1:%2:%3]").arg(getUAVFieldValue(objManager, "FlightModeSettings", "FlightModePosition", 0))
.arg(getUAVFieldValue(objManager, "FlightModeSettings", "FlightModePosition", 1))
.arg(getUAVFieldValue(objManager, "FlightModeSettings", "FlightModePosition", 2));
}
}
void UsageTrackerPlugin::onFinished(QNetworkReply *reply)
{
if (reply->error() == QNetworkReply::NoError) {
getGeneralSettings()->setLastUsageHash(m_lastHash);
qDebug() << "Updated last usage hash to:" << m_lastHash;
} else {
qDebug() << "Usage tracking failed with:" << reply->errorString();
}
}
QString UsageTrackerPlugin::getUAVFieldValue(UAVObjectManager *objManager, QString objectName, QString fieldName, int index) const
{
UAVObject *object = objManager->getObject(objectName);
if (object != NULL) {
UAVObjectField *field = object->getField(fieldName);
if (field != NULL) {
return field->getValue(index).toString();
}
}
return tr("Unknown");
}
QString UsageTrackerPlugin::getQueryHash(QString source) const
{
source += "OpenPilot Fuck Yeah!";
return QString(QCryptographicHash::hash(QByteArray(source.toStdString().c_str()), QCryptographicHash::Md5).toHex());
}
Core::Internal::GeneralSettings *UsageTrackerPlugin::getGeneralSettings() const
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
Core::Internal::GeneralSettings *settings = pm->getObject<Core::Internal::GeneralSettings>();
return settings;
}
bool UsageTrackerPlugin::shouldSend(const QString &hash)
{
if (getGeneralSettings()->lastUsageHash() == hash) {
return false;
} else {
m_lastHash = hash;
return true;
}
}

View File

@ -0,0 +1,63 @@
/**
******************************************************************************
*
* @file usagetrackerplugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup UsageTrackerPlugin Usage Tracker Plugin
* @{
* @brief A plugin tracking GCS usage
*****************************************************************************/
/*
* 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 USAGETRACKERPLUGIN_H
#define USAGETRACKERPLUGIN_H
#include <extensionsystem/iplugin.h>
#include <coreplugin/generalsettings.h>
class TelemetryManager;
class UAVObjectManager;
class QNetworkReply;
class UsageTrackerPlugin : public ExtensionSystem::IPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID "OpenPilot.UsageTracker")
public:
UsageTrackerPlugin();
~UsageTrackerPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString *errorString);
void shutdown();
private slots:
void onAutopilotConnect();
void trackUsage();
void collectUsageParameters(QMap<QString, QString> &parameters);
void onFinished(QNetworkReply *reply);
private:
TelemetryManager *m_telemetryManager;
QString m_lastHash;
QString getUAVFieldValue(UAVObjectManager *objManager, QString objectName, QString fieldName, int index = 0) const;
QString getQueryHash(QString source) const;
Core::Internal::GeneralSettings *getGeneralSettings() const;
bool shouldSend(const QString &hash);
};
#endif // USAGETRACKERPLUGIN_H