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


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 04:02:48