websocket_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 "websocket_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 
31 #include "ui_websocket_server.h"
32 
33 class WebsocketDialog : public QDialog
34 {
35 public:
36  WebsocketDialog() : QDialog(nullptr), ui(new Ui::WebSocketDialog)
37  {
38  ui->setupUi(this);
39  ui->lineEditPort->setValidator(new QIntValidator());
40  setWindowTitle("WebSocket Server");
41 
42  connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
43  connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
44  }
46  {
47  while (ui->layoutOptions->count() > 0)
48  {
49  auto item = ui->layoutOptions->takeAt(0);
50  item->widget()->setParent(nullptr);
51  }
52  delete ui;
53  }
54  Ui::WebSocketDialog* ui;
55 };
56 
58  : _running(false), _server("plotJuggler", QWebSocketServer::NonSecureMode)
59 {
60  connect(&_server, &QWebSocketServer::newConnection, this,
62 }
63 
65 {
66  shutdown();
67 }
68 
69 bool WebsocketServer::start(QStringList*)
70 {
71  if (_running)
72  {
73  return _running;
74  }
75 
76  if (parserFactories() == nullptr || parserFactories()->empty())
77  {
78  QMessageBox::warning(nullptr, tr("Websocket Server"),
79  tr("No available MessageParsers"), QMessageBox::Ok);
80  _running = false;
81  return false;
82  }
83 
84  bool ok = false;
85 
86  WebsocketDialog* dialog = new WebsocketDialog();
87 
88  for (const auto& it : *parserFactories())
89  {
90  dialog->ui->comboBoxProtocol->addItem(it.first);
91 
92  if (auto widget = it.second->optionsWidget())
93  {
94  widget->setVisible(false);
95  dialog->ui->layoutOptions->addWidget(widget);
96  }
97  }
98 
99  // load previous values
100  QSettings settings;
101  QString protocol = settings.value("WebsocketServer::protocol", "JSON").toString();
102  int port = settings.value("WebsocketServer::port", 9871).toInt();
103 
104  dialog->ui->lineEditPort->setText(QString::number(port));
105 
106  ParserFactoryPlugin::Ptr parser_creator;
107 
108  connect(dialog->ui->comboBoxProtocol,
109  qOverload<const QString&>(&QComboBox::currentIndexChanged), this,
110  [&](const QString& selected_protocol) {
111  if (parser_creator)
112  {
113  if (auto prev_widget = parser_creator->optionsWidget())
114  {
115  prev_widget->setVisible(false);
116  }
117  }
118  parser_creator = parserFactories()->at(selected_protocol);
119 
120  if (auto widget = parser_creator->optionsWidget())
121  {
122  widget->setVisible(true);
123  }
124  });
125 
126  dialog->ui->comboBoxProtocol->setCurrentText(protocol);
127 
128  int res = dialog->exec();
129  if (res == QDialog::Rejected)
130  {
131  _running = false;
132  return false;
133  }
134 
135  port = dialog->ui->lineEditPort->text().toUShort(&ok);
136  protocol = dialog->ui->comboBoxProtocol->currentText();
137  dialog->deleteLater();
138 
139  _parser = parser_creator->createParser({}, {}, {}, dataMap());
140 
141  // save back to service
142  settings.setValue("WebsocketServer::protocol", protocol);
143  settings.setValue("WebsocketServer::port", port);
144 
145  if (_server.listen(QHostAddress::Any, port))
146  {
147  qDebug() << "Websocket listening on port" << port;
148  _running = true;
149  }
150  else
151  {
152  QMessageBox::warning(nullptr, tr("Websocket Server"),
153  tr("Couldn't open websocket on port %1").arg(port),
154  QMessageBox::Ok);
155  _running = false;
156  }
157 
158  return _running;
159 }
160 
162 {
163  if (_running)
164  {
166  _server.close();
167  _running = false;
168  }
169 }
170 
172 {
173  QWebSocket* pSocket = _server.nextPendingConnection();
174  connect(pSocket, &QWebSocket::textMessageReceived, this,
176  connect(pSocket, &QWebSocket::disconnected, this, &WebsocketServer::socketDisconnected);
177  _clients << pSocket;
178 }
179 
180 void WebsocketServer::processMessage(QString message)
181 {
182  std::lock_guard<std::mutex> lock(mutex());
183 
184  using namespace std::chrono;
185  auto ts = high_resolution_clock::now().time_since_epoch();
186  double timestamp = 1e-6 * double(duration_cast<microseconds>(ts).count());
187 
188  QByteArray bmsg = message.toLocal8Bit();
189  MessageRef msg(reinterpret_cast<uint8_t*>(bmsg.data()), bmsg.size());
190 
191  try
192  {
193  _parser->parseMessage(msg, timestamp);
194  }
195  catch (std::exception& err)
196  {
197  QMessageBox::warning(nullptr, tr("Websocket Server"),
198  tr("Problem parsing the message. Websocket Server will be "
199  "stopped.\n%1")
200  .arg(err.what()),
201  QMessageBox::Ok);
202  shutdown();
203  emit closed();
204  return;
205  }
206  emit dataReceived();
207  return;
208 }
209 
211 {
212  QWebSocket* pClient = qobject_cast<QWebSocket*>(sender());
213  if (pClient)
214  {
215  disconnect(pClient, &QWebSocket::textMessageReceived, this,
217  disconnect(pClient, &QWebSocket::disconnected, this,
219  _clients.removeAll(pClient);
220  pClient->deleteLater();
221  }
222 }
WebsocketDialog
Definition: websocket_server.cpp:33
WebsocketServer::processMessage
void processMessage(QString message)
Definition: websocket_server.cpp:180
WebsocketServer::_parser
PJ::MessageParserPtr _parser
Definition: websocket_server.h:64
WebsocketServer::socketDisconnected
void socketDisconnected()
Definition: websocket_server.cpp:210
WebsocketServer::start
virtual bool start(QStringList *) override
start streaming.
Definition: websocket_server.cpp:69
arg
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition: core.h:1875
mqtt_test_proto.msg
msg
Definition: mqtt_test_proto.py:43
WebsocketDialog::ui
Ui::WebSocketDialog * ui
Definition: websocket_server.cpp:54
ok
ROSCPP_DECL bool ok()
WebsocketServer::shutdown
virtual void shutdown() override
shutdown Stop streaming
Definition: websocket_server.cpp:161
websocket_server.h
detail::count
constexpr auto count() -> size_t
Definition: core.h:1222
Ui
Definition: cheatsheet_dialog.h:6
PJ::DataStreamer::parserFactories
const ParserFactories * parserFactories() const
Definition: datastreamer_base.cpp:34
WebsocketServer::_clients
QList< QWebSocket * > _clients
Definition: websocket_server.h:62
PJ::DataStreamer::closed
void closed()
PJ::ParserFactoryPlugin::Ptr
std::shared_ptr< ParserFactoryPlugin > Ptr
Definition: messageparser_base.h:142
WebsocketServer::onNewConnection
void onNewConnection()
Definition: websocket_server.cpp:171
PJ::DataStreamer::dataReceived
void dataReceived()
WebsocketServer::_server
QWebSocketServer _server
Definition: websocket_server.h:63
PJ::MessageRef
Definition: messageparser_base.h:28
PJ::DataStreamer::mutex
std::mutex & mutex()
Definition: datastreamer_base.h:62
WebsocketDialog::~WebsocketDialog
~WebsocketDialog()
Definition: websocket_server.cpp:45
WebsocketServer::~WebsocketServer
virtual ~WebsocketServer() override
Definition: websocket_server.cpp:64
WebsocketServer::_running
bool _running
Definition: websocket_server.h:61
WebsocketDialog::WebsocketDialog
WebsocketDialog()
Definition: websocket_server.cpp:36
nullptr
#define nullptr
Definition: backward.hpp:386
WebsocketServer::WebsocketServer
WebsocketServer()
Definition: websocket_server.cpp:57


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Aug 11 2024 02:24:26