2 ******************************************************************************
4 * @file IPconnectionplugin.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * @addtogroup GCSPlugins GCS Plugins
8 * @addtogroup IPConnPlugin IP Telemetry Plugin
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
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>
45 #include <coreplugin/threadmanager.h>
49 // Communication between IPconnectionConnection::OpenDevice() and IPConnection::onOpenDevice()
51 QWaitCondition openDeviceWait
;
52 QWaitCondition closeDeviceWait
;
53 // QReadWriteLock dummyLock;
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()
72 void IPConnection::onOpenDevice(QString HostName
, int Port
, bool UseTCP
)
74 QAbstractSocket
*ipSocket
;
75 const int Timeout
= 5 * 1000;
79 ipSocket
= new QTcpSocket(this);
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";
89 ipSocket
->connectToHost(HostName
, Port
);
91 // in blocking mode so we wait for the connection to succeed
92 if (ipSocket
->waitForConnected(Timeout
)) {
94 openDeviceWait
.wakeAll();
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.*/
104 openDeviceWait
.wakeAll();
108 void IPConnection::onCloseDevice(QAbstractSocket
*ipSocket
)
113 closeDeviceWait
.wakeAll();
118 IPConnection
*connection
= 0;
120 IPconnectionConnection::IPconnectionConnection()
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);
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...
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
;
163 if (m_config
->HostName().length() > 1) {
164 d
.displayName
= (const QString
)m_config
->HostName();
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
175 QIODevice
*IPconnectionConnection::openDevice(const QString
&)
182 // get the configuration info
183 HostName
= m_config
->HostName();
184 Port
= m_config
->Port();
185 UseTCP
= m_config
->UseTCP();
188 // Andrew: close any existing socket... this should never occur
190 emit
CloseSocket(ipSocket
);
191 closeDeviceWait
.wait(&ipConMutex
);
197 emit
CreateSocket(HostName
, Port
, UseTCP
);
198 openDeviceWait
.wait(&ipConMutex
);
201 if (ipSocket
== NULL
) {
202 msgBox
.setText((const QString
)errorMsg
);
208 void IPconnectionConnection::closeDevice(const QString
&)
212 emit
CloseSocket(ipSocket
);
213 closeDeviceWait
.wait(&ipConMutex
);
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");
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
)
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());