udp_server.cpp
Go to the documentation of this file.
1 /*Wensocket PlotJuggler Plugin license(Faircode, Davide Faconti)
2 
3 Copyright(C) 2018 Philippe Gauthier - ISIR - UPMC
4 Copyright(C) 2020 Davide Faconti
5 Permission is hereby granted to any person obtaining a copy of this software and
6 associated documentation files(the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use, copy, modify, merge, publish,
8 distribute, sublicense, and / or sell copies("Use") of the Software, and to permit persons
9 to whom the Software is furnished to do so. The above copyright notice and this permission
10 notice shall be included in all copies or substantial portions of the Software. THE
11 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
12 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
14 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
15 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 THE SOFTWARE.
17 */
18 #include "udp_server.h"
19 #include <QTextStream>
20 #include <QFile>
21 #include <QMessageBox>
22 #include <QDebug>
23 #include <QSettings>
24 #include <QDialog>
25 #include <mutex>
26 #include <QWebSocket>
27 #include <QIntValidator>
28 #include <QMessageBox>
29 #include <chrono>
30 #include <QNetworkDatagram>
31 
32 #include "ui_udp_server.h"
33 
34 class UdpServerDialog : public QDialog
35 {
36 public:
37  UdpServerDialog() : QDialog(nullptr), ui(new Ui::UDPServerDialog)
38  {
39  ui->setupUi(this);
40  ui->lineEditPort->setValidator(new QIntValidator());
41  setWindowTitle("UDP Server");
42 
43  connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
44  connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
45  }
47  {
48  while (ui->layoutOptions->count() > 0)
49  {
50  auto item = ui->layoutOptions->takeAt(0);
51  item->widget()->setParent(nullptr);
52  }
53  delete ui;
54  }
55  Ui::UDPServerDialog* ui;
56 };
57 
58 UDP_Server::UDP_Server() : _running(false)
59 {
60 }
61 
63 {
64  shutdown();
65 }
66 
67 bool UDP_Server::start(QStringList*)
68 {
69  if (_running)
70  {
71  return _running;
72  }
73 
74  if (parserFactories() == nullptr || parserFactories()->empty())
75  {
76  QMessageBox::warning(nullptr, tr("UDP Server"), tr("No available MessageParsers"),
77  QMessageBox::Ok);
78  _running = false;
79  return false;
80  }
81 
82  bool ok = false;
83 
84  UdpServerDialog dialog;
85 
86  for (const auto& it : *parserFactories())
87  {
88  dialog.ui->comboBoxProtocol->addItem(it.first);
89 
90  if (auto widget = it.second->optionsWidget())
91  {
92  widget->setVisible(false);
93  dialog.ui->layoutOptions->addWidget(widget);
94  }
95  }
96 
97  // load previous values
98  QSettings settings;
99  QString protocol = settings.value("UDP_Server::protocol", "JSON").toString();
100  int port = settings.value("UDP_Server::port", 9870).toInt();
101 
102  dialog.ui->lineEditPort->setText(QString::number(port));
103 
104  ParserFactoryPlugin::Ptr parser_creator;
105 
106  connect(dialog.ui->comboBoxProtocol,
107  qOverload<const QString &>(&QComboBox::currentIndexChanged),
108  this, [&](const QString & selected_protocol) {
109  if (parser_creator)
110  {
111  if( auto prev_widget = parser_creator->optionsWidget())
112  {
113  prev_widget->setVisible(false);
114  }
115  }
116  parser_creator = parserFactories()->at(selected_protocol);
117 
118  if (auto widget = parser_creator->optionsWidget())
119  {
120  widget->setVisible(true);
121  }
122  });
123 
124  dialog.ui->comboBoxProtocol->setCurrentText(protocol);
125 
126  int res = dialog.exec();
127  if (res == QDialog::Rejected)
128  {
129  _running = false;
130  return false;
131  }
132 
133  port = dialog.ui->lineEditPort->text().toUShort(&ok);
134  protocol = dialog.ui->comboBoxProtocol->currentText();
135 
136  _parser = parser_creator->createParser({}, {}, {}, dataMap());
137 
138  // save back to service
139  settings.setValue("UDP_Server::protocol", protocol);
140  settings.setValue("UDP_Server::port", port);
141 
142  _udp_socket = new QUdpSocket();
143  _udp_socket->bind(QHostAddress::Any, port);
144 
145  connect(_udp_socket, &QUdpSocket::readyRead, this, &UDP_Server::processMessage);
146 
147  if (_udp_socket)
148  {
149  qDebug() << "UDP listening on port" << port;
150  _running = true;
151  }
152  else
153  {
154  QMessageBox::warning(nullptr, tr("UDP Server"),
155  tr("Couldn't bind UDP port %1").arg(port), QMessageBox::Ok);
156  _running = false;
157  }
158 
159  return _running;
160 }
161 
163 {
164  if (_running && _udp_socket)
165  {
166  _udp_socket->deleteLater();
167  _running = false;
168  }
169 }
170 
172 {
173  while (_udp_socket->hasPendingDatagrams())
174  {
175  QNetworkDatagram datagram = _udp_socket->receiveDatagram();
176 
177  using namespace std::chrono;
178  auto ts = high_resolution_clock::now().time_since_epoch();
179  double timestamp = 1e-6 * double(duration_cast<microseconds>(ts).count());
180 
181  QByteArray m = datagram.data();
182  MessageRef msg(reinterpret_cast<uint8_t*>(m.data()), m.count());
183 
184  try
185  {
186  std::lock_guard<std::mutex> lock(mutex());
187  // important use the mutex to protect any access to the data
188  _parser->parseMessage(msg, timestamp);
189  }
190  catch (std::exception& err)
191  {
192  QMessageBox::warning(nullptr, tr("UDP Server"),
193  tr("Problem parsing the message. UDP Server will be "
194  "stopped.\n%1")
195  .arg(err.what()),
196  QMessageBox::Ok);
197  shutdown();
198  // notify the GUI
199  emit closed();
200  return;
201  }
202  }
203  // notify the GUI
204  emit dataReceived();
205  return;
206 }
virtual ~UDP_Server() override
Definition: udp_server.cpp:62
#define nullptr
Definition: backward.hpp:386
std::shared_ptr< ParserFactoryPlugin > Ptr
virtual void shutdown() override
shutdown Stop streaming
Definition: udp_server.cpp:162
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition: core.h:1736
std::mutex & mutex()
bool _running
Definition: udp_server.h:58
Definition: lz4.c:1706
const ParserFactories * parserFactories() const
constexpr auto count() -> size_t
Definition: core.h:1050
PlotDataMapRef & dataMap()
QUdpSocket * _udp_socket
Definition: udp_server.h:59
virtual bool start(QStringList *) override
start streaming.
Definition: udp_server.cpp:67
void processMessage()
Definition: udp_server.cpp:171
Ui::UDPServerDialog * ui
Definition: udp_server.cpp:55
PJ::MessageParserPtr _parser
Definition: udp_server.h:60


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Jun 19 2023 03:12:53