LP-56 - Better txpid option namings, fix tabs-spaces, tooltips. headers, variable...
[librepilot.git] / ground / openpilotgcs / src / plugins / ipconnection / ipconnectionplugin.cpp
blobdb1f6ed5b2b384c15635f5ac3887a0c1f7eda939
1 /**
2 ******************************************************************************
4 * @file IPconnectionplugin.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * @addtogroup GCSPlugins GCS Plugins
7 * @{
8 * @addtogroup IPConnPlugin IP Telemetry Plugin
9 * @{
10 * @brief IP Connection Plugin impliment telemetry over TCP/IP and UDP/IP
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 // The core of this plugin has been directly copied from the serial plugin and converted to work over a TCP link instead of a direct serial link
30 #include "ipconnectionplugin.h"
33 #include <extensionsystem/pluginmanager.h>
34 #include <coreplugin/icore.h>
35 #include "ipconnection_internal.h"
37 #include <QtCore/QtPlugin>
38 #include <QMainWindow>
39 #include <QMessageBox>
40 #include <QtNetwork/QAbstractSocket>
41 #include <QtNetwork/QTcpSocket>
42 #include <QtNetwork/QUdpSocket>
43 #include <QWaitCondition>
44 #include <QMutex>
45 #include <coreplugin/threadmanager.h>
47 #include <QDebug>
49 // Communication between IPconnectionConnection::OpenDevice() and IPConnection::onOpenDevice()
50 QString errorMsg;
51 QWaitCondition openDeviceWait;
52 QWaitCondition closeDeviceWait;
53 // QReadWriteLock dummyLock;
54 QMutex ipConMutex;
55 QAbstractSocket *ret;
57 IPConnection::IPConnection(IPconnectionConnection *connection) : QObject()
59 moveToThread(Core::ICore::instance()->threadManager()->getRealTimeThread());
61 QObject::connect(connection, SIGNAL(CreateSocket(QString, int, bool)),
62 this, SLOT(onOpenDevice(QString, int, bool)));
63 QObject::connect(connection, SIGNAL(CloseSocket(QAbstractSocket *)),
64 this, SLOT(onCloseDevice(QAbstractSocket *)));
67 /*IPConnection::~IPConnection()
70 }*/
72 void IPConnection::onOpenDevice(QString HostName, int Port, bool UseTCP)
74 QAbstractSocket *ipSocket;
75 const int Timeout = 5 * 1000;
77 ipConMutex.lock();
78 if (UseTCP) {
79 ipSocket = new QTcpSocket(this);
80 } else {
81 ipSocket = new QUdpSocket(this);
84 // do sanity check on hostname and port...
85 if ((HostName.length() == 0) || (Port < 1)) {
86 errorMsg = "Please configure Host and Port options before opening the connection";
87 } else {
88 // try to connect...
89 ipSocket->connectToHost(HostName, Port);
91 // in blocking mode so we wait for the connection to succeed
92 if (ipSocket->waitForConnected(Timeout)) {
93 ret = ipSocket;
94 openDeviceWait.wakeAll();
95 ipConMutex.unlock();
96 return;
98 // tell user something went wrong
99 errorMsg = ipSocket->errorString();
101 /* BUGBUG TODO - returning null here leads to segfault because some caller still calls disconnect without checking our return value properly
102 * someone needs to debug this, I got lost in the calling chain.*/
103 ret = NULL;
104 openDeviceWait.wakeAll();
105 ipConMutex.unlock();
108 void IPConnection::onCloseDevice(QAbstractSocket *ipSocket)
110 ipConMutex.lock();
111 ipSocket->close();
112 delete (ipSocket);
113 closeDeviceWait.wakeAll();
114 ipConMutex.unlock();
118 IPConnection *connection = 0;
120 IPconnectionConnection::IPconnectionConnection()
122 ipSocket = NULL;
123 // create all our objects
124 m_config = new IPconnectionConfiguration("IP Network Telemetry", NULL, this);
125 m_config->restoresettings();
127 m_optionspage = new IPconnectionOptionsPage(m_config, this);
129 if (!connection) {
130 connection = new IPConnection(this);
133 // just signal whenever we have a device event...
134 QMainWindow *mw = Core::ICore::instance()->mainWindow();
135 QObject::connect(mw, SIGNAL(deviceChange()),
136 this, SLOT(onEnumerationChanged()));
137 QObject::connect(m_optionspage, SIGNAL(availableDevChanged()),
138 this, SLOT(onEnumerationChanged()));
141 IPconnectionConnection::~IPconnectionConnection()
142 { // clean up out resources...
143 if (ipSocket) {
144 ipSocket->close();
145 delete (ipSocket);
147 if (connection) {
148 delete connection;
149 connection = NULL;
153 void IPconnectionConnection::onEnumerationChanged()
154 { // no change from serial plugin
155 emit availableDevChanged(this);
159 QList <Core::IConnection::device> IPconnectionConnection::availableDevices()
161 QList <Core::IConnection::device> list;
162 device d;
163 if (m_config->HostName().length() > 1) {
164 d.displayName = (const QString)m_config->HostName();
165 } else {
166 d.displayName = "Unconfigured";
168 d.name = (const QString)m_config->HostName();
169 // we only have one "device" as defined by the configuration m_config
170 list.append(d);
172 return list;
175 QIODevice *IPconnectionConnection::openDevice(const QString &)
177 QString HostName;
178 int Port;
179 bool UseTCP;
180 QMessageBox msgBox;
182 // get the configuration info
183 HostName = m_config->HostName();
184 Port = m_config->Port();
185 UseTCP = m_config->UseTCP();
187 if (ipSocket) {
188 // Andrew: close any existing socket... this should never occur
189 ipConMutex.lock();
190 emit CloseSocket(ipSocket);
191 closeDeviceWait.wait(&ipConMutex);
192 ipConMutex.unlock();
193 ipSocket = NULL;
196 ipConMutex.lock();
197 emit CreateSocket(HostName, Port, UseTCP);
198 openDeviceWait.wait(&ipConMutex);
199 ipConMutex.unlock();
200 ipSocket = ret;
201 if (ipSocket == NULL) {
202 msgBox.setText((const QString)errorMsg);
203 msgBox.exec();
205 return ipSocket;
208 void IPconnectionConnection::closeDevice(const QString &)
210 if (ipSocket) {
211 ipConMutex.lock();
212 emit CloseSocket(ipSocket);
213 closeDeviceWait.wait(&ipConMutex);
214 ipConMutex.unlock();
215 ipSocket = NULL;
220 QString IPconnectionConnection::connectionName()
221 { // updated from serial plugin
222 return QString("Network telemetry port");
225 QString IPconnectionConnection::shortName()
226 { // updated from serial plugin
227 if (m_config->UseTCP()) {
228 return QString("TCP");
229 } else {
230 return QString("UDP");
235 IPconnectionPlugin::IPconnectionPlugin()
236 { // no change from serial plugin
239 IPconnectionPlugin::~IPconnectionPlugin()
240 { // manually remove the options page object
241 removeObject(m_connection->Optionspage());
244 void IPconnectionPlugin::extensionsInitialized()
246 addAutoReleasedObject(m_connection);
249 bool IPconnectionPlugin::initialize(const QStringList &arguments, QString *errorString)
251 Q_UNUSED(arguments);
252 Q_UNUSED(errorString);
253 m_connection = new IPconnectionConnection();
254 // must manage this registration of child object ourselves
255 // if we use an autorelease here it causes the GCS to crash
256 // as it is deleting objects as the app closes...
257 addObject(m_connection->Optionspage());
259 return true;