dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
ipconnectionplugin.cpp
Go to the documentation of this file.
1 
13 /*
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  * for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  *
27  * Additional note on redistribution: The copyright and license notices above
28  * must be maintained in each individual source file that is a derivative work
29  * of this source file; otherwise redistribution is prohibited.
30  */
31 
32 #include "ipconnectionplugin.h"
33 
35 #include <coreplugin/icore.h>
36 
37 #include <QtCore/QtPlugin>
38 #include <QMainWindow>
39 #include <QMessageBox>
40 #include <QtNetwork/QAbstractSocket>
41 #include <QtNetwork/QTcpSocket>
42 #include <QtNetwork/QUdpSocket>
43 
44 #include <QDebug>
45 
47 
49 {
50  ipSocket = NULL;
51  // create all our objects
52  m_config = new IPConnectionConfiguration("IP Network Telemetry", NULL, this);
53  m_config->readConfig();
54 
55  m_optionspage = new IPConnectionOptionsPage(m_config, this);
56 
57  // only way our devices change is through the options page
58  QObject::connect(m_optionspage, &IPConnectionOptionsPage::availableDevChanged, this,
60  // we loaded some devices from configuration file...
62 }
63 
65 { // clean up our resources...
66  if (ipSocket) {
67  ipSocket->close();
68  delete (ipSocket);
69  }
70 }
71 
73 {
74  emit availableDevChanged(this);
75 }
76 
78 {
79  const auto &newHosts = m_config->hosts();
80 
81  // add new devices
82  for (const auto &host : newHosts) {
83  bool found = false;
84  for (auto dev : devices) {
85  if (static_cast<const IPDevice *>(dev)->host() == host) {
86  found = true;
87  break;
88  }
89  }
90  if (!found) {
91  auto dev = new IPDevice();
92  QString name =
93  QString("%0://%1:%2")
94  .arg(host.protocol == IPConnectionConfiguration::ProtocolTcp ? "tcp" : "udp")
95  .arg(host.hostname)
96  .arg(host.port);
97  dev->setDisplayName(name);
98  dev->setName(name);
99  dev->setHost(host);
100  devices.append(dev); // TODO: memory leak, seems like an awkward interface..?
101  }
102  }
103 
104  // clear out removed devices
105  for (int i = 0; i < devices.length();) {
106  if (!newHosts.contains(static_cast<const IPDevice *>(devices.at(i))->host())) {
107  devices.at(i)->deleteLater();
108  devices.removeAt(i);
109  } else {
110  i++;
111  }
112  }
113 
114  return devices;
115 }
116 
118 {
119  auto *dev = qobject_cast<IPDevice *>(device);
120  if (!dev)
121  return nullptr;
122 
123  const int timeout = 5 * 1000;
124 
125  if (dev->host().protocol == IPConnectionConfiguration::ProtocolTcp) {
126  ipSocket = new QTcpSocket(this);
127  } else {
128  ipSocket = new QUdpSocket(this);
129  }
130 
131  // Disable Nagle algorithm to try and get data promptly rather than
132  // minimize packets.
133  ipSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
134 
135  // Allow reuse of ports, so if we're running the simulator and GCS on
136  // the same host, and simulator crashes leaving ports in FIN_WAIT, we
137  // can restart simulator immediately.
138  ipSocket->bind(0, QAbstractSocket::ShareAddress);
139 
140  // do sanity check on hostname and port...
141  if (!dev->host().hostname.length() || dev->host().port < 1 || dev->host().port > 65535) {
142  errorMsg = tr("Please configure host and port options before opening the connection");
143  } else {
144  // try to connect...
145  ipSocket->connectToHost(dev->host().hostname, static_cast<quint16>(dev->host().port));
146 
147  // in blocking mode so we wait for the connection to succeed
148  if (ipSocket->waitForConnected(timeout)) {
149  return ipSocket;
150  }
151 
152  // tell user what went wrong
153  errorMsg = ipSocket->errorString();
154 
155  delete ipSocket;
156  ipSocket = nullptr;
157 
158  QMessageBox msgBox(QMessageBox::Critical, tr("Connection Failed"), errorMsg,
159  QMessageBox::Ok,
160  static_cast<QWidget *>(Core::ICore::instance()->mainWindow()));
161  msgBox.exec();
162  }
163 
164  return nullptr;
165 }
166 
167 void IPConnection::closeDevice(const QString &)
168 {
169  if (ipSocket) {
170  ipSocket->close();
171  delete ipSocket;
172  ipSocket = NULL;
173  }
174 }
175 
177 {
178  return QString("Network telemetry port");
179 }
180 
182 {
183  return tr("IP");
184 }
185 
186 IPConnectionPlugin::IPConnectionPlugin()
187 { // no change from serial plugin
188 }
189 
190 IPConnectionPlugin::~IPConnectionPlugin()
191 { // manually remove the options page object
192  removeObject(m_connection->optionsPage());
193 }
194 
195 void IPConnectionPlugin::extensionsInitialized()
196 {
197  addAutoReleasedObject(m_connection);
198 }
199 
200 bool IPConnectionPlugin::initialize(const QStringList &arguments, QString *errorString)
201 {
202  Q_UNUSED(arguments);
203  Q_UNUSED(errorString);
204  m_connection = new IPConnection();
205  // must manage this registration of child object ourselves
206  // if we use an autorelease here it causes the GCS to crash
207  // as it is deleting objects as the app closes...
208  addObject(m_connection->optionsPage());
209 
210  return true;
211 }
212 
213 /*void IPConnectionPlugin::readConfig(QSettings *settings, Core::UAVConfigInfo *configInfo)
214 {
215 
216 }
217 
218 void IPConnectionPlugin::saveConfig(QSettings *settings, Core::UAVConfigInfo *configInfo)
219 {
220 
221 }*/
void availableDevChanged(IConnection *)
void addObject(QObject *obj)
Definition: iplugin.cpp:291
virtual ~IPConnection()
for i
Definition: OPPlots.m:140
virtual QIODevice * openDevice(Core::IDevice *deviceName)
virtual QList< Core::IDevice * > availableDevices()
virtual QString shortName()
IPConnectionOptionsPage * optionsPage() const
static ICore * instance()
Definition: coreimpl.cpp:46
void removeObject(QObject *obj)
Definition: iplugin.cpp:317
IPConnection * connection
Definition: icore.h:39
virtual void closeDevice(const QString &deviceName)
void addAutoReleasedObject(QObject *obj)
Definition: iplugin.cpp:306
The IPDevice class.
Definition: ipdevice.h:37
virtual QString connectionName()