diff --git a/.gitmodules b/.gitmodules index b2e852b7c..8b1378917 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1 @@ -[submodule "3rdparty/paho.mqtt.c"] - path = 3rdparty/paho.mqtt.c - url = https://github.com/eclipse/paho.mqtt.c.git -[submodule "3rdparty/liblsl"] - path = 3rdparty/liblsl - url = https://github.com/PlotJuggler/liblsl.git + diff --git a/3rdparty/liblsl b/3rdparty/liblsl deleted file mode 160000 index 65ffb6934..000000000 --- a/3rdparty/liblsl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 65ffb6934b9e1ba7de5be3570a06ec70afdfedaa diff --git a/3rdparty/paho.mqtt.c b/3rdparty/paho.mqtt.c deleted file mode 160000 index e4c375752..000000000 --- a/3rdparty/paho.mqtt.c +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e4c3757524a272c086e369cda5a56b8f766a401a diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fb393982..39c9ed9cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,51 +197,8 @@ endif() add_subdirectory( 3rdparty/color_widgets ) add_subdirectory( 3rdparty/Qt-Advanced-Docking ) add_subdirectory( 3rdparty/qwt/src ) - add_subdirectory( 3rdparty/lua-5.4.1 ) -find_package(Git QUIET) -if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") -# Update submodules as needed - option(GIT_SUBMODULE "Check submodules during build" ON) - if(GIT_SUBMODULE) - message(STATUS "Submodule update") - execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE GIT_SUBMOD_RESULT) - if(NOT GIT_SUBMOD_RESULT EQUAL "0") - message("git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") - endif() - endif() -endif() - -if(EXISTS "${PROJECT_SOURCE_DIR}/3rdparty/paho.mqtt.c/CMakeLists.txt") - SET(PAHO_ENABLE_TESTING FALSE CACHE BOOL "Build tests and run" FORCE) - SET(PAHO_ENABLE_CPACK FALSE CACHE BOOL "Enable CPack" FORCE) - - if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - SET(PAHO_BUILD_STATIC FALSE CACHE BOOL "Build static library" FORCE) - SET(PAHO_BUILD_SHARED TRUE CACHE BOOL "Build shared library" FORCE) - else() - SET(PAHO_BUILD_STATIC TRUE CACHE BOOL "Build static library" FORCE) - SET(PAHO_BUILD_SHARED FALSE CACHE BOOL "Build shared library" FORCE) - endif() - - SET(CMAKE_INSTALL_INCLUDEDIR ) - - #add_subdirectory( 3rdparty/paho.mqtt.c EXCLUDE_FROM_ALL) - #add_subdirectory( plotjuggler_plugins/DataStreamMQTT ) -endif() - -if(EXISTS "${PROJECT_SOURCE_DIR}/3rdparty/liblsl/CMakeLists.txt" AND NOT WIN32) - SET(LSL_ENABLE_TESTING FALSE CACHE BOOL "Build tests and run" FORCE) - SET(LSL_ENABLE_CPACK FALSE CACHE BOOL "Enable CPack" FORCE) - SET(LSL_BUILD_STATIC TRUE CACHE BOOL "Build static library" FORCE) - SET(LSL_BUILD_SHARED FALSE CACHE BOOL "Build shared library" FORCE) - #add_subdirectory( 3rdparty/liblsl ) - #add_subdirectory( plotjuggler_plugins/DataStreamLSL ) -endif() - add_subdirectory( plotjuggler_app ) add_subdirectory( plotjuggler_plugins/DataLoadCSV ) diff --git a/README.md b/README.md index ea5451317..74b4b1537 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Alternatively, you may download the Snaps version that include the ROS1 plugins: Clone the repository as usual: - git clone --recurse-submodules https://github.com/facontidavide/PlotJuggler.git + git clone https://github.com/facontidavide/PlotJuggler.git The only binary dependency that you need installed in your system is Qt5. On Ubuntu, the debians can be installed with the the command: diff --git a/plotjuggler_plugins/DataStreamMQTT/CMakeLists.txt b/plotjuggler_plugins/DataStreamMQTT/CMakeLists.txt deleted file mode 100644 index 09e5b6830..000000000 --- a/plotjuggler_plugins/DataStreamMQTT/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ - -include_directories( - ../../include - paho.mqtt.c/src) - -add_definitions(${QT_DEFINITIONS}) -add_definitions(-DQT_PLUGIN) - -QT5_WRAP_UI ( UI_SRC datastream_mqtt.ui ) - -SET( SRC datastream_mqtt.cpp ) - -add_library(DataStreamMQTT SHARED ${SRC} ${UI_SRC} ) - -if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - target_link_libraries(DataStreamMQTT - ${Qt5Widgets_LIBRARIES} plotjuggler_plugin_base - paho-mqtt3c - paho-mqtt3a ) -else() - target_link_libraries(DataStreamMQTT - ${Qt5Widgets_LIBRARIES} plotjuggler_plugin_base - paho-mqtt3c-static - paho-mqtt3a-static) -endif() - -install(TARGETS DataStreamMQTT DESTINATION ${PJ_PLUGIN_INSTALL_DIRECTORY} ) - - - - diff --git a/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.cpp b/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.cpp deleted file mode 100644 index 432b7afb3..000000000 --- a/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.cpp +++ /dev/null @@ -1,391 +0,0 @@ -#include "datastream_mqtt.h" -#include "ui_datastream_mqtt.h" -#include -#include -#include -#include - -class MQTT_Dialog: public QDialog -{ -public: - MQTT_Dialog(): - QDialog(nullptr), - ui(new Ui::DataStreamMQTT) - { - ui->setupUi(this); - - static QString uuid = QString::number(rand()); - ui->lineEditClientID->setText(tr("Plotjuggler-") + uuid); - } - - ~MQTT_Dialog() { - while( ui->layoutOptions->count() > 0) - { - auto item = ui->layoutOptions->takeAt(0); - item->widget()->setParent(nullptr); - } - delete ui; - } - - Ui::DataStreamMQTT* ui; -}; - -//--------------------------------------------- - -QString Code(int rc) -{ - switch(rc) - { - case MQTTASYNC_FAILURE: return"FAILURE"; - case MQTTASYNC_PERSISTENCE_ERROR: return"PERSISTENCE_ERROR"; - case MQTTASYNC_DISCONNECTED: return"DISCONNECTED"; - case MQTTASYNC_MAX_MESSAGES_INFLIGHT: return"MAX_MESSAGES_INFLIGHT"; - case MQTTASYNC_BAD_UTF8_STRING: return"BAD_UTF8_STRING"; - case MQTTASYNC_NULL_PARAMETER: return"NULL_PARAMETER"; - case MQTTASYNC_TOPICNAME_TRUNCATED: return"TOPICNAME_TRUNCATED"; - case MQTTASYNC_BAD_STRUCTURE: return"BAD_STRUCTURE"; - case MQTTASYNC_BAD_QOS: return"BAD_QOS"; - case MQTTASYNC_NO_MORE_MSGIDS: return"NO_MORE_MSGIDS"; - case MQTTASYNC_OPERATION_INCOMPLETE: return"OPERATION_INCOMPLETE"; - case MQTTASYNC_MAX_BUFFERED_MESSAGES: return"MAX_BUFFERED_MESSAGES"; - case MQTTASYNC_SSL_NOT_SUPPORTED: return"SSL_NOT_SUPPORTED"; - case MQTTASYNC_BAD_PROTOCOL: return"BAD_PROTOCOL"; - case MQTTASYNC_BAD_MQTT_OPTION: return"BAD_MQTT_OPTION"; - case MQTTASYNC_WRONG_MQTT_VERSION: return"WRONG_MQTT_VERSION"; - case MQTTASYNC_0_LEN_WILL_TOPIC: return"0_LEN_WILL_TOPIC"; - } - return QString::number(rc); -} - -void ConnectionLost(void *context, char *cause) -{ - DataStreamMQTT* _this = static_cast(context); - - MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; - - qDebug() <<"MQTT Connection lost. Reconnecting..."; - - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - - int rc = MQTTAsync_connect(_this->_client, &conn_opts); - - if (rc != MQTTASYNC_SUCCESS) - { - _this->_error_msg = QString("Failed to start connect, return code %1").arg(Code(rc)); - _this->_finished = true; - } -} - -int MessageArrived(void *context, char *topicName, - int topicLen, MQTTAsync_message *message) -{ - DataStreamMQTT* _this = static_cast(context); - - auto it = _this->_parsers.find(topicName); - if( it == _this->_parsers.end() ) - { - auto parser = _this->availableParsers()->at( _this->_protocol )->createInstance({}, _this->dataMap()); - it = _this->_parsers.insert( {topicName, parser} ).first; - } - auto& parser = it->second; - - try { - MessageRef msg( static_cast(message->payload), message->payloadlen); - - using namespace std::chrono; - auto ts = high_resolution_clock::now().time_since_epoch(); - double timestamp = 1e-6* double( duration_cast(ts).count() ); - - parser->parseMessage(msg, timestamp); - - } catch (std::exception& ) { - _this->_protocol_issue = true; - return 0; - } - -// printf(" topic: %s\n", topicName); -// printf(" message: %.*s\n", message->payloadlen, (char*)message->payload); - MQTTAsync_freeMessage(&message); - MQTTAsync_free(topicName); - - emit _this->dataReceived(); - return 1; -} - -void onDisconnectFailure(void* context, MQTTAsync_failureData* response) -{ - DataStreamMQTT* _this = static_cast(context); - _this->_disconnection_done = true; -} - -void onDisconnect(void* context, MQTTAsync_successData* response) -{ - DataStreamMQTT* _this = static_cast(context); - _this->_disconnection_done = true; -} - -void onSubscribe(void* context, MQTTAsync_successData* response) -{ - DataStreamMQTT* _this = static_cast(context); - _this->_subscribed = true; -} - -void onSubscribeFailure(void* context, MQTTAsync_failureData* response) -{ - DataStreamMQTT* _this = static_cast(context); - _this->_error_msg = QString("Subscription Failure. Code %1").arg(Code(response->code)); - _this->_finished = true; -} - - -void onConnectFailure(void* context, MQTTAsync_failureData* response) -{ - DataStreamMQTT* _this = static_cast(context); - _this->_error_msg = QString("Connection Failure. Code %1").arg(Code(response->code)); - _this->_finished = true; -} - - -void onConnect(void* context, MQTTAsync_successData* response) -{ - DataStreamMQTT* _this = static_cast(context); - MQTTAsync client = _this->_client; - - MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; - - opts.onSuccess = onSubscribe; - opts.onFailure = onSubscribeFailure; - opts.context = _this; - - int rc = MQTTAsync_subscribe( - client, - _this->_topic_filter.toStdString().c_str(), - _this->_qos, - &opts); - - if ( rc != MQTTASYNC_SUCCESS) - { - _this->_error_msg = QString("Failed to start subscribe, return code %1").arg(Code(rc)); - _this->_finished = true; - } -} - - -DataStreamMQTT::DataStreamMQTT(): - _protocol_issue(false), - _running(false) -{ - _protocol_issue_timer.setSingleShot(false); - _protocol_issue_timer.setInterval(500); - - connect(&_protocol_issue_timer, &QTimer::timeout, this, - [this](){ - if(_protocol_issue){ - _protocol_issue = false; - shutdown(); - - QMessageBox::warning(nullptr,tr("DataStream MQTT"), - tr("Exception while parsing the message. Probably the format was not recognized (%1 used)").arg( this->_protocol), - QMessageBox::Ok); - emit this->closed(); - - } - }); -} - -bool DataStreamMQTT::start(QStringList *) -{ - if (_running) - { - return _running; - } - - if( !availableParsers() ) - { - QMessageBox::warning(nullptr,tr("Websocket Server"), tr("No available MessageParsers"), QMessageBox::Ok); - _running = false; - return false; - } - - MQTT_Dialog* dialog = new MQTT_Dialog(); - - for( const auto& it: *availableParsers()) - { - dialog->ui->comboBoxProtocol->addItem( it.first ); - - if(auto widget = it.second->optionsWidget() ) - { - widget->setVisible(false); - dialog->ui->layoutOptions->addWidget( widget ); - } - } - - std::shared_ptr parser_creator; - - connect(dialog->ui->comboBoxProtocol, qOverload( &QComboBox::currentIndexChanged), this, - [&](int index) - { - if( parser_creator ){ - QWidget* prev_widget = parser_creator->optionsWidget(); - prev_widget->setVisible(false); - } - QString protocol = dialog->ui->comboBoxProtocol->itemText(index); - parser_creator = availableParsers()->at( protocol ); - - if(auto widget = parser_creator->optionsWidget() ){ - widget->setVisible(true); - } - }); - - // load previous values - QSettings settings; - QString address = settings.value("DataStreamMQTT::address").toString(); - _protocol = settings.value("DataStreamMQTT::protocol", "JSON").toString(); - _topic_filter = settings.value("DataStreamMQTT::filter").toString(); - _qos = settings.value("DataStreamMQTT::qos", 0).toInt(); - QString username = settings.value("DataStreamMQTT::username", "").toString(); - QString password = settings.value("DataStreamMQTT::password", "").toString(); - - dialog->ui->lineEditAddress->setText( address ); - dialog->ui->comboBoxProtocol->setCurrentText(_protocol); - dialog->ui->lineEditTopicFilter->setText( _topic_filter ); - dialog->ui->comboBoxQoS->setCurrentIndex(_qos); - dialog->ui->lineEditUsername->setText(username); - dialog->ui->lineEditPassword->setText(password); - - if( dialog->exec() == QDialog::Rejected ) - { - return false; - } - - address = dialog->ui->lineEditAddress->text(); - _protocol = dialog->ui->comboBoxProtocol->currentText(); - _topic_filter = dialog->ui->lineEditTopicFilter->text(); - _qos = dialog->ui->comboBoxQoS->currentIndex(); - QString cliend_id = dialog->ui->lineEditClientID->text(); - username = dialog->ui->lineEditUsername->text(); - password = dialog->ui->lineEditPassword->text(); - - dialog->deleteLater(); - - // save back to service - settings.setValue("DataStreamMQTT::address", address); - settings.setValue("DataStreamMQTT::filter", _topic_filter); - settings.setValue("DataStreamMQTT::protocol", _protocol); - settings.setValue("DataStreamMQTT::qos", _qos); - settings.setValue("DataStreamMQTT::username", username); - settings.setValue("DataStreamMQTT::password", password); - - _subscribed = false; - _finished = false; - _protocol_issue = false; - - MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; - - int rc = MQTTAsync_create(&_client, - address.toStdString().c_str(), - cliend_id.toStdString().c_str(), - MQTTCLIENT_PERSISTENCE_NONE, - nullptr); - - if (rc != MQTTASYNC_SUCCESS) - { - QMessageBox::warning(nullptr,tr("DataStream MQTT"), - tr("Failed create client MQTT. Error code %1").arg(Code(rc)), - QMessageBox::Ok); - return false; - } - - rc = MQTTAsync_setCallbacks(_client, this, ConnectionLost, MessageArrived, nullptr); - if (rc != MQTTASYNC_SUCCESS) - { - QMessageBox::warning(nullptr,tr("DataStream MQTT"), - tr("Failed to set callbacks. Error code %1").arg(Code(rc)), - QMessageBox::Ok); - MQTTAsync_destroy(&_client); - return false; - } - - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - conn_opts.onSuccess = onConnect; - conn_opts.onFailure = onConnectFailure; - conn_opts.context = this; - conn_opts.username = username.toStdString().c_str(); - conn_opts.password = password.toStdString().c_str(); - - rc = MQTTAsync_connect(_client, &conn_opts); - - if (rc != MQTTASYNC_SUCCESS) - { - QMessageBox::warning(nullptr,tr("DataStream MQTT"), - tr("Failed to start connection. Error code %1").arg(Code(rc)), - QMessageBox::Ok); - MQTTAsync_destroy(&_client); - return false; - } - - while (!_subscribed && !_finished) - { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - - if (_finished) - { - QMessageBox::warning(nullptr,tr("DataStream MQTT"), - tr("Failed to start connection. Message: %1").arg(_error_msg), - QMessageBox::Ok); - MQTTAsync_destroy(&_client); - return false; - } - - _running = true; - _protocol_issue_timer.start(500); - return _running; -} - -void DataStreamMQTT::shutdown() -{ - if( _running ) - { - _disconnection_done = false; - MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer; - - disc_opts.context = this; - disc_opts.onSuccess = onDisconnect; - disc_opts.onFailure = onDisconnectFailure; - - int rc = MQTTAsync_disconnect(_client, &disc_opts); - if (rc != MQTTASYNC_SUCCESS) - { - QMessageBox::warning(nullptr,tr("DataStream MQTT"), - tr("Failed to disconned cleanly. Error code %1").arg(rc), - QMessageBox::Ok); - MQTTAsync_destroy(&_client); - _running = false; - return; - } - - while (!_disconnection_done) - { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - - MQTTAsync_destroy(&_client); - _running = false; - _parsers.clear(); - } -} - -bool DataStreamMQTT::isRunning() const -{ - return _running; -} - -DataStreamMQTT::~DataStreamMQTT() -{ - shutdown(); -} - - diff --git a/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.h b/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.h deleted file mode 100644 index 5638dca1d..000000000 --- a/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef DATASTREAM_MQTT_H -#define DATASTREAM_MQTT_H - -#include -#include -#include -#include -#include "PlotJuggler/datastreamer_base.h" -#include "PlotJuggler/messageparser_base.h" - -#include "MQTTAsync.h" - -using namespace PJ; - -class DataStreamMQTT : public PJ::DataStreamer -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "facontidavide.PlotJuggler3.DataStreamer") - Q_INTERFACES(PJ::DataStreamer) - -public: - DataStreamMQTT(); - - virtual bool start(QStringList*) override; - - virtual void shutdown() override; - - virtual bool isRunning() const override; - - virtual ~DataStreamMQTT() override; - - virtual const char* name() const override - { - return "MQTT Subscriber"; - } - - virtual bool isDebugPlugin() override - { - return false; - } - - bool _disconnection_done; - bool _subscribed; - bool _finished; - MQTTAsync _client; - - QString _error_msg; - - QString _protocol; - QString _topic_filter; - int _qos; - std::unordered_map _parsers; - - bool _protocol_issue; - QTimer _protocol_issue_timer; - -private: - bool _running; - -private slots: - -}; - - -#endif // DATASTREAM_MQTT_H diff --git a/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.ui b/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.ui deleted file mode 100644 index 8fbdb22e3..000000000 --- a/plotjuggler_plugins/DataStreamMQTT/datastream_mqtt.ui +++ /dev/null @@ -1,240 +0,0 @@ - - - DataStreamMQTT - - - - 0 - 0 - 379 - 349 - - - - MQTT Subscriber - - - - - - - 12 - 75 - true - - - - Connections details: - - - - - - - - - - - - Client ID: - - - - - - - - - - Topics prefix: - - - - - - - - - - QoS: - - - - - - - - - - 0 - - - - - 1 - - - - - 2 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Full address: - - - - - - - Username: - - - - - - - Password: - - - - - - - - - - QLineEdit::Password - - - - - - - - - - 12 - 75 - true - - - - Message Protocol: - - - - - - - - - - - 75 - true - - - - - 0 - - - 6 - - - 0 - - - 6 - - - - - Protocol options: - - - - - - - - - - Qt::Vertical - - - - 20 - 11 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - DataStreamMQTT - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - DataStreamMQTT - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/plotjuggler_plugins/DataStreamMQTT/mqtt_test.py b/plotjuggler_plugins/DataStreamMQTT/mqtt_test.py deleted file mode 100644 index 441795b59..000000000 --- a/plotjuggler_plugins/DataStreamMQTT/mqtt_test.py +++ /dev/null @@ -1,31 +0,0 @@ -import paho.mqtt.client as mqtt -import math -import json -from time import sleep - -# The callback for when the client receives a CONNACK response from the server. -def on_connect(client, userdata, flags, rc): - print("Connected with result code "+str(rc)) - -client = mqtt.Client() -client.on_connect = on_connect - -client = mqtt.Client("PlotJuggler-test") #create new instance - -client.connect("127.0.0.1", 1883, 60) - -time = 0.0 - -while True: - sleep(0.20) - time += 0.20 - data = { - "timestamp": time, - "test_data": { - "cos": math.cos(time), - "sin": math.sin(time) - } - } - - ret = client.publish("plotjuggler/stuff", json.dumps(data), qos=0 ) - print( ret.is_published() ) \ No newline at end of file