Commit d0113827 authored by Gus Grubba's avatar Gus Grubba

Initial Taisync link integration

parent 5e63260b
......@@ -59,6 +59,7 @@ linux {
CONFIG += MacBuild
CONFIG += x86_64
CONFIG -= x86
DEFINES += QGC_GST_TAISYNC_ENABLED
equals(QT_MAJOR_VERSION, 5) | greaterThan(QT_MINOR_VERSION, 5) {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
} else {
......@@ -83,6 +84,7 @@ linux {
DEFINES += QGC_NO_GOOGLE_MAPS
DEFINES += NO_SERIAL_LINK
DEFINES += QGC_DISABLE_UVC
DEFINES += QGC_GST_TAISYNC_ENABLED
QMAKE_IOS_DEPLOYMENT_TARGET = 8.0
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 1,2 # Universal
QMAKE_LFLAGS += -Wl,-no_pie
......
......@@ -5,7 +5,7 @@ if [ ! -d /Volumes/RAMDisk ] ; then
exit 1
fi
#-- Set to my local installation
QMAKE=/Users/gus/Applications/Qt/5.11.0/ios/bin/qmake
QMAKE=/Users/gus/Applications/Qt/5.11.2/ios/bin/qmake
#-- Using Travis variables as this will eventually live there
SHADOW_BUILD_DIR=/Volumes/RAMDisk/build-qgroundcontrol-iOS-Release
TRAVIS_BUILD_DIR=/Users/gus/github/work/UpstreamQGC
......
......@@ -1106,6 +1106,27 @@ SOURCES += \
src/FactSystem/ParameterManager.cc \
src/FactSystem/SettingsFact.cc \
#-------------------------------------------------------------------------------------
# Taisync
contains (DEFINES, QGC_GST_TAISYNC_ENABLED) {
INCLUDEPATH += \
src/Taisync
HEADERS += \
src/comm/TaisyncLink.h \
src/Taisync/TaisyncHandler.h \
src/Taisync/TaisyncSettings.h \
src/Taisync/TaisyncTelemetry.h \
src/Taisync/TaisyncVideoReceiver.h \
SOURCES += \
src/comm/TaisyncLink.cc \
src/Taisync/TaisyncHandler.cc \
src/Taisync/TaisyncSettings.cc \
src/Taisync/TaisyncTelemetry.cc \
src/Taisync/TaisyncVideoReceiver.cc \
}
#-------------------------------------------------------------------------------------
# AirMap
......
......@@ -199,6 +199,7 @@
<file alias="SurveyItemEditor.qml">src/PlanView/SurveyItemEditor.qml</file>
<file alias="SyslinkComponent.qml">src/AutoPilotPlugins/Common/SyslinkComponent.qml</file>
<file alias="TcpSettings.qml">src/ui/preferences/TcpSettings.qml</file>
<file alias="TaisyncSettings.qml">src/Taisync/TaisyncSettings.qml</file>
<file alias="test.qml">src/test.qml</file>
<file alias="UdpSettings.qml">src/ui/preferences/UdpSettings.qml</file>
<file alias="ValuePageWidget.qml">src/FlightMap/Widgets/ValuePageWidget.qml</file>
......
......@@ -60,7 +60,13 @@ public:
/// @param settingsGroup Group to place settings in for QSettings::setGroup
SettingsGroup(const QString &name, const QString &settingsGroup, QObject* parent = nullptr);
Q_PROPERTY(bool visible MEMBER _visible CONSTANT)
Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged)
virtual bool visible () { return _visible; }
virtual void setVisible (bool vis) { _visible = vis; emit visibleChanged(); }
signals:
void visibleChanged ();
protected:
SettingsFact* _createSettingsFact(const QString& factName);
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "TaisyncHandler.h"
#include "SettingsManager.h"
#include "QGCApplication.h"
#include "VideoManager.h"
QGC_LOGGING_CATEGORY(TaisyncLog, "TaisyncLog")
//-----------------------------------------------------------------------------
TaisyncHandler::TaisyncHandler(QObject* parent)
: QObject (parent)
{
}
//-----------------------------------------------------------------------------
TaisyncHandler::~TaisyncHandler()
{
close();
}
//-----------------------------------------------------------------------------
void
TaisyncHandler::close()
{
qCDebug(TaisyncLog) << "Close Taisync TCP";
if(_tcpSocket) {
_tcpSocket->close();
_tcpSocket->deleteLater();
_tcpSocket = nullptr;
}
}
//-----------------------------------------------------------------------------
void
TaisyncHandler::_start(uint16_t port)
{
qCDebug(TaisyncLog) << "Start Taisync TCP on port" << port;
_tcpServer = new QTcpServer(this);
QObject::connect(_tcpServer, &QTcpServer::newConnection, this, &TaisyncHandler::_newConnection);
_tcpServer->listen(QHostAddress::AnyIPv4, port);
}
//-----------------------------------------------------------------------------
void
TaisyncHandler::_newConnection()
{
qCDebug(TaisyncLog) << "New Taisync TCP Connection";
if(_tcpSocket) {
_tcpSocket->close();
_tcpSocket->deleteLater();
}
_tcpSocket = _tcpServer->nextPendingConnection();
QObject::connect(_tcpSocket, &QIODevice::readyRead, this, &TaisyncHandler::_readBytes);
}
//-----------------------------------------------------------------------------
void
TaisyncHandler::_socketDisconnected()
{
qCDebug(TaisyncLog) << "Taisync Telemetry Connection Closed";
if(_tcpSocket) {
_tcpSocket->close();
_tcpSocket->deleteLater();
_tcpSocket = nullptr;
}
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "QGCLoggingCategory.h"
#include <QTcpServer>
#include <QTcpSocket>
#define TAISYNC_VIDEO_UDP_PORT 5600
#define TAISYNC_VIDEO_TCP_PORT 8000
#define TAISYNC_SETTINGS_PORT 8200
#define TAISYNC_TELEM_PORT 8400
Q_DECLARE_LOGGING_CATEGORY(TaisyncLog)
class TaisyncHandler : public QObject
{
Q_OBJECT
public:
explicit TaisyncHandler (QObject* parent = nullptr);
~TaisyncHandler ();
virtual void start () = 0;
virtual void close ();
protected:
virtual void _start (uint16_t port);
protected slots:
virtual void _newConnection ();
virtual void _socketDisconnected ();
virtual void _readBytes () = 0;
protected:
QTcpServer* _tcpServer = nullptr;
QTcpSocket* _tcpSocket = nullptr;
};
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "TaisyncSettings.h"
#include "SettingsManager.h"
#include "QGCApplication.h"
#include "VideoManager.h"
QGC_LOGGING_CATEGORY(TaisyncSettingsLog, "TaisyncSettingsLog")
//-----------------------------------------------------------------------------
TaisyncSettings::TaisyncSettings(QObject* parent)
: TaisyncHandler(parent)
{
}
//-----------------------------------------------------------------------------
void
TaisyncSettings::start()
{
qCDebug(TaisyncSettingsLog) << "Start Taisync Settings";
_start(TAISYNC_SETTINGS_PORT);
}
//-----------------------------------------------------------------------------
void
TaisyncSettings::_readBytes()
{
QByteArray bytesIn = _tcpSocket->read(_tcpSocket->bytesAvailable());
qCDebug(TaisyncSettingsLog) << "Taisync settings data:" << bytesIn.size();
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "TaisyncHandler.h"
Q_DECLARE_LOGGING_CATEGORY(TaisyncSettingsLog)
class TaisyncSettings : public TaisyncHandler
{
Q_OBJECT
public:
explicit TaisyncSettings (QObject* parent = nullptr);
void start () override;
protected slots:
void _readBytes () override;
};
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
Column {
id: _taisyncSettings
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.margins: ScreenTools.defaultFontPixelWidth
function saveSettings() {
if(subEditConfig) {
subEditConfig.videoEnabled = videoEnableCheck.checked
}
}
QGCCheckBox {
id: videoEnableCheck
text: qsTr("Enable Taisync video link")
Component.onCompleted: {
checked = subEditConfig && subEditConfig.linkType === LinkConfiguration.TypeTaisync ? subEditConfig.videoEnabled : false
}
}
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "TaisyncTelemetry.h"
#include "SettingsManager.h"
#include "QGCApplication.h"
#include "VideoManager.h"
QGC_LOGGING_CATEGORY(TaisyncTelemetryLog, "TaisyncTelemetryLog")
//-----------------------------------------------------------------------------
TaisyncTelemetry::TaisyncTelemetry(QObject* parent)
: TaisyncHandler(parent)
{
}
//-----------------------------------------------------------------------------
void
TaisyncTelemetry::close()
{
TaisyncHandler::close();
qCDebug(TaisyncTelemetryLog) << "Close Taisync Telemetry";
}
//-----------------------------------------------------------------------------
void
TaisyncTelemetry::start()
{
qCDebug(TaisyncTelemetryLog) << "Start Taisync Telemetry";
_start(TAISYNC_TELEM_PORT);
}
//-----------------------------------------------------------------------------
void
TaisyncTelemetry::writeBytes(QByteArray bytes)
{
if(_tcpSocket) {
_tcpSocket->write(bytes);
}
}
//-----------------------------------------------------------------------------
void
TaisyncTelemetry::_newConnection()
{
TaisyncHandler::_newConnection();
qCDebug(TaisyncTelemetryLog) << "New Taisync Temeletry Connection";
}
//-----------------------------------------------------------------------------
void
TaisyncTelemetry::_readBytes()
{
while(_tcpSocket->bytesAvailable()) {
QByteArray bytesIn = _tcpSocket->read(_tcpSocket->bytesAvailable());
emit bytesReady(bytesIn);
}
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "TaisyncHandler.h"
#include <QUdpSocket>
#include <QTimer>
Q_DECLARE_LOGGING_CATEGORY(TaisyncTelemetryLog)
class TaisyncTelemetry : public TaisyncHandler
{
Q_OBJECT
public:
explicit TaisyncTelemetry (QObject* parent = nullptr);
void close () override;
void start () override;
void writeBytes (QByteArray bytes);
signals:
void bytesReady (QByteArray bytes);
private slots:
void _newConnection () override;
void _readBytes () override;
};
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "TaisyncVideoReceiver.h"
#include "SettingsManager.h"
#include "QGCApplication.h"
#include "VideoManager.h"
QGC_LOGGING_CATEGORY(TaisyncVideoReceiverLog, "TaisyncVideoReceiverLog")
//-----------------------------------------------------------------------------
TaisyncVideoReceiver::TaisyncVideoReceiver(QObject* parent)
: TaisyncHandler(parent)
{
}
//-----------------------------------------------------------------------------
void
TaisyncVideoReceiver::close()
{
TaisyncHandler::close();
qCDebug(TaisyncVideoReceiverLog) << "Close Taisync Video Receiver";
if(_udpVideoSocket) {
_udpVideoSocket->close();
_udpVideoSocket->deleteLater();
_udpVideoSocket = nullptr;
}
}
//-----------------------------------------------------------------------------
void
TaisyncVideoReceiver::start()
{
qCDebug(TaisyncVideoReceiverLog) << "Start Taisync Video Receiver";
_udpVideoSocket = new QUdpSocket(this);
_start(TAISYNC_VIDEO_TCP_PORT);
}
//-----------------------------------------------------------------------------
void
TaisyncVideoReceiver::_readBytes()
{
QByteArray bytesIn = _tcpSocket->read(_tcpSocket->bytesAvailable());
_udpVideoSocket->writeDatagram(bytesIn, QHostAddress::LocalHost, TAISYNC_VIDEO_UDP_PORT);
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "TaisyncHandler.h"
#include <QUdpSocket>
Q_DECLARE_LOGGING_CATEGORY(TaisyncVideoReceiverLog)
class TaisyncVideoReceiver : public TaisyncHandler
{
Q_OBJECT
public:
explicit TaisyncVideoReceiver (QObject* parent = nullptr);
void start () override;
void close () override;
private slots:
void _readBytes () override;
private:
QUdpSocket* _udpVideoSocket = nullptr;
};
......@@ -29,11 +29,14 @@
#ifdef QT_DEBUG
#include "MockLink.h"
#endif
#if defined(QGC_GST_TAISYNC_ENABLED)
#include "TaisyncLink.h"
#endif
#define LINK_SETTING_ROOT "LinkConfigurations"
LinkConfiguration::LinkConfiguration(const QString& name)
: _link(NULL)
: _link(nullptr)
, _name(name)
, _dynamic(false)
, _autoConnect(false)
......@@ -80,7 +83,7 @@ const QString LinkConfiguration::settingsRoot()
*/
LinkConfiguration* LinkConfiguration::createSettings(int type, const QString& name)
{
LinkConfiguration* config = NULL;
LinkConfiguration* config = nullptr;
switch(type) {
#ifndef NO_SERIAL_LINK
case LinkConfiguration::TypeSerial:
......@@ -107,6 +110,11 @@ LinkConfiguration* LinkConfiguration::createSettings(int type, const QString& na
case LinkConfiguration::TypeMock:
config = new MockConfiguration(name);
break;
#endif
#if defined(QGC_GST_TAISYNC_ENABLED)
case LinkConfiguration::TypeTaisync:
config = new TaisyncConfiguration(name);
break;
#endif
}
return config;
......@@ -118,7 +126,7 @@ LinkConfiguration* LinkConfiguration::createSettings(int type, const QString& na
*/
LinkConfiguration* LinkConfiguration::duplicateSettings(LinkConfiguration* source)
{
LinkConfiguration* dupe = NULL;
LinkConfiguration* dupe = nullptr;
switch(source->type()) {
#ifndef NO_SERIAL_LINK
case TypeSerial:
......@@ -145,9 +153,13 @@ LinkConfiguration* LinkConfiguration::duplicateSettings(LinkConfiguration* sourc
case TypeMock:
dupe = new MockConfiguration(dynamic_cast<MockConfiguration*>(source));
break;
#endif
#if defined(QGC_GST_TAISYNC_ENABLED)
case TypeTaisync:
dupe = new TaisyncConfiguration(dynamic_cast<TaisyncConfiguration*>(source));
break;
#endif
case TypeLast:
default:
break;
}
return dupe;
......
......@@ -51,6 +51,9 @@ public:
#endif
TypeUdp, ///< UDP Link
TypeTcp, ///< TCP Link
#if defined(QGC_GST_TAISYNC_ENABLED)
TypeTaisync,
#endif
#ifdef QGC_ENABLE_BLUETOOTH
TypeBluetooth, ///< Bluetooth Link
#endif
......
......@@ -24,6 +24,9 @@
#ifdef QGC_ENABLE_BLUETOOTH
#include "BluetoothLink.h"
#endif
#if defined(QGC_GST_TAISYNC_ENABLED)
#include "TaisyncLink.h"
#endif
#ifndef __mobile__
#include "GPSManager.h"
......@@ -49,11 +52,11 @@ LinkManager::LinkManager(QGCApplication* app, QGCToolbox* toolbox)
, _configurationsLoaded(false)
, _connectionsSuspended(false)
, _mavlinkChannelsUsedBitMask(1) // We never use channel 0 to avoid sequence numbering problems
, _autoConnectSettings(NULL)
, _mavlinkProtocol(NULL)
, _autoConnectSettings(nullptr)
, _mavlinkProtocol(nullptr)
#ifndef __mobile__
#ifndef NO_SERIAL_LINK
, _nmeaPort(NULL)
, _nmeaPort(nullptr)
#endif
#endif
{
......@@ -104,11 +107,11 @@ void LinkManager::createConnectedLink(LinkConfiguration* config)
LinkInterface* LinkManager::createConnectedLink(SharedLinkConfigurationPointer& config, bool isPX4Flow)
{
if (!config) {
qWarning() << "LinkManager::createConnectedLink called with NULL config";
return NULL;
qWarning() << "LinkManager::createConnectedLink called with nullptr config";
return nullptr;
}
LinkInterface* pLink = NULL;
LinkInterface* pLink = nullptr;
switch(config->type()) {
#ifndef NO_SERIAL_LINK
case LinkConfiguration::TypeSerial:
......@@ -117,7 +120,7 @@ LinkInterface* LinkManager::createConnectedLink(SharedLinkConfigurationPointer&
if (serialConfig) {
pLink = new SerialLink(config, isPX4Flow);
if (serialConfig->usbDirect()) {
_activeLinkCheckList.append((SerialLink*)pLink);
_activeLinkCheckList.append(dynamic_cast<SerialLink*>(pLink));
if (!_activeLinkCheckTimer.isActive()) {
_activeLinkCheckTimer.start();
}
......@@ -148,17 +151,19 @@ LinkInterface* LinkManager::createConnectedLink(SharedLinkConfigurationPointer&
case LinkConfiguration::TypeMock:
pLink = new MockLink(config);
break;
#endif
#if defined(QGC_GST_TAISYNC_ENABLED)
case LinkConfiguration::TypeTaisync:
pLink = new TaisyncLink(config);
break;
#endif
case LinkConfiguration::TypeLast:
default:
break;
}
if (pLink) {
_addLink(pLink);
connectLink(pLink);
}
return pLink;
}
......@@ -174,7 +179,7 @@ LinkInterface* LinkManager::createConnectedLink(const QString& name)
}
}
}
return NULL;
return nullptr;
}
void LinkManager::_addLink(LinkInterface* link)
......@@ -289,8 +294,8 @@ SharedLinkInterfacePointer LinkManager::sharedLinkInterfacePointerForLink(LinkIn
}
}
qWarning() << "LinkManager::sharedLinkInterfaceForLink returning NULL";
return SharedLinkInterfacePointer(NULL);
qWarning() << "LinkManager::sharedLinkInterfaceForLink returning nullptr";
return SharedLinkInterfacePointer(nullptr);
}
/// @brief If all new connections should be suspended a message is displayed to the user and true
......@@ -371,42 +376,46 @@ void LinkManager::loadLinkConfigurationList()
QString root(LinkConfiguration::settingsRoot());
root += QString("/Link%1").arg(i);
if(settings.contains(root + "/type")) {
int type = settings.value(root + "/type").toInt();
if((LinkConfiguration::LinkType)type < LinkConfiguration::TypeLast) {
LinkConfiguration::LinkType type = static_cast<LinkConfiguration::LinkType>(settings.value(root + "/type").toInt());
if(type < LinkConfiguration::TypeLast) {
if(settings.contains(root + "/name")) {
QString name = settings.value(root + "/name").toString();
if(!name.isEmpty()) {
LinkConfiguration* pLink = NULL;
LinkConfiguration* pLink = nullptr;
bool autoConnect = settings.value(root + "/auto").toBool();
bool highLatency = settings.value(root + "/high_latency").toBool();
switch((LinkConfiguration::LinkType)type) {
switch(type) {
#ifndef NO_SERIAL_LINK
case LinkConfiguration::TypeSerial:
pLink = (LinkConfiguration*)new SerialConfiguration(name);
pLink = dynamic_cast<LinkConfiguration*>(new SerialConfiguration(name));
break;
#endif
case LinkConfiguration::TypeUdp:
pLink = (LinkConfiguration*)new UDPConfiguration(name);
pLink = dynamic_cast<LinkConfiguration*>(new UDPConfiguration(name));
break;
case LinkConfiguration::TypeTcp:
pLink = (LinkConfiguration*)new TCPConfiguration(name);
pLink = dynamic_cast<LinkConfiguration*>(new TCPConfiguration(name));
break;
#ifdef QGC_ENABLE_BLUETOOTH
case LinkConfiguration::TypeBluetooth:
pLink = (LinkConfiguration*)new BluetoothConfiguration(name);
pLink = dynamic_cast<LinkConfiguration*>(new BluetoothConfiguration(name));
break;
#endif
#ifndef __mobile__
case LinkConfiguration::TypeLogReplay:
pLink = (LinkConfiguration*)new LogReplayLinkConfiguration(name);
pLink = dynamic_cast<LinkConfiguration*>(new LogReplayLinkConfiguration(name));
break;
#endif
#ifdef QT_DEBUG
case LinkConfiguration::TypeMock:
pLink = (LinkConfiguration*)new MockConfiguration(name);
pLink = dynamic_cast<LinkConfiguration*>(new MockConfiguration(name));
break;
#endif
#if defined(QGC_GST_TAISYNC_ENABLED)
case LinkConfiguration::TypeTaisync:
pLink = dynamic_cast<LinkConfiguration*>(new TaisyncConfiguration(name));
break;
#endif
default:
case LinkConfiguration::TypeLast:
break;
}
......@@ -456,7 +465,7 @@ SerialConfiguration* LinkManager::_autoconnectConfigurationsContainsPort(const Q
qWarning() << "Internal error";
}
}
return NULL;
return nullptr;
}
#endif
......@@ -465,10 +474,9 @@ void LinkManager::_updateAutoConnectLinks(void)
if (_connectionsSuspended || qgcApp()->runningUnitTests()) {
return;
}
// Re-add UDP if we need to
bool foundUDP = false;
for (int i=0; i<_sharedLinks.count(); i++) {
for (int i = 0; i < _sharedLinks.count(); i++) {
LinkConfiguration* linkConfig = _sharedLinks[i]->getLinkConfiguration();
if (linkConfig->type() == LinkConfiguration::TypeUdp && linkConfig->name() == _defaultUPDLinkName) {
foundUDP = true;
......@@ -477,7 +485,7 @@ void LinkManager::_updateAutoConnectLinks(void)
}
if (!foundUDP && _autoConnectSettings->autoConnectUDP()->rawValue().toBool()) {
qCDebug(LinkManagerLog) << "New auto-connect UDP port added";
// Default UDPConfiguration is set up for autoconnect
//-- Default UDPConfiguration is set up for autoconnect