diff --git a/.gitignore b/.gitignore index 378eac2..b3d0bdc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ build +.clangd +.vscode \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cd2e6e..a867ddd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,18 +2,17 @@ cmake_minimum_required(VERSION 3.10) project(mqttExplorer) set(CMAKE_CXX_STANDARD 17) +set(CMAKE_EXPORT_COMPILE_COMMANDS true) +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -#PAHO-MQTT-C Library -#USUALLY INSTALLED TO /usr/local/include /usr/local/lib and /usr/local/bin -include_directories(/usr/local/include) -link_directories(/usr/local/lib) -set(LIBS ${LIBS} paho-mqtt3cs) +include_directories("/usr/local/include") +include_directories("/usr/local/include/mqttpp-0.1") +link_directories("/usr/local/lib/mqttpp-0.1") find_package(spdlog CONFIG REQUIRED) -find_package(ZLIB REQUIRED) -add_executable(mqttExplorer src/main.cpp src/MQTT.cpp) +add_executable(mqttExplorer src/main.cpp) -target_link_libraries(mqttExplorer ${LIBS} spdlog::spdlog ZLIB::ZLIB) +target_link_libraries(mqttExplorer spdlog::spdlog mqttpp) install(TARGETS mqttExplorer DESTINATION bin) diff --git a/src/.MQTT.cpp.swp b/src/.MQTT.cpp.swp deleted file mode 100644 index c2c770c..0000000 Binary files a/src/.MQTT.cpp.swp and /dev/null differ diff --git a/src/.main.cpp.swp b/src/.main.cpp.swp deleted file mode 100644 index 37b70db..0000000 Binary files a/src/.main.cpp.swp and /dev/null differ diff --git a/src/MQTT.cpp b/src/MQTT.cpp deleted file mode 100644 index fdf216e..0000000 --- a/src/MQTT.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// -// Created by Julian-Steffen Müller on 24.01.20. -// - -#include -#include "MQTT.h" -#include "string.h" -#include -#include "spdlog/spdlog.h" - -#define MOSQ_ERR_SUCCESS 1 -#define MOSQ_ERR_INVAL 2 - -/* Does a topic match a subscription? */ -int topic_match(const char *sub, const char *topic, bool *result) -{ - size_t spos; - - if(!result) return MOSQ_ERR_INVAL; - *result = false; - - if(!sub || !topic || sub[0] == 0 || topic[0] == 0){ - return MOSQ_ERR_INVAL; - } - - if((sub[0] == '$' && topic[0] != '$') - || (topic[0] == '$' && sub[0] != '$')){ - - return MOSQ_ERR_SUCCESS; - } - - spos = 0; - - while(sub[0] != 0){ - if(topic[0] == '+' || topic[0] == '#'){ - return MOSQ_ERR_INVAL; - } - if(sub[0] != topic[0] || topic[0] == 0){ /* Check for wildcard matches */ - if(sub[0] == '+'){ - /* Check for bad "+foo" or "a/+foo" subscription */ - if(spos > 0 && sub[-1] != '/'){ - return MOSQ_ERR_INVAL; - } - /* Check for bad "foo+" or "foo+/a" subscription */ - if(sub[1] != 0 && sub[1] != '/'){ - return MOSQ_ERR_INVAL; - } - spos++; - sub++; - while(topic[0] != 0 && topic[0] != '/'){ - if(topic[0] == '+' || topic[0] == '#'){ - return MOSQ_ERR_INVAL; - } - topic++; - } - if(topic[0] == 0 && sub[0] == 0){ - *result = true; - return MOSQ_ERR_SUCCESS; - } - }else if(sub[0] == '#'){ - /* Check for bad "foo#" subscription */ - if(spos > 0 && sub[-1] != '/'){ - return MOSQ_ERR_INVAL; - } - /* Check for # not the final character of the sub, e.g. "#foo" */ - if(sub[1] != 0){ - return MOSQ_ERR_INVAL; - }else{ - while(topic[0] != 0){ - if(topic[0] == '+' || topic[0] == '#'){ - return MOSQ_ERR_INVAL; - } - topic++; - } - *result = true; - return MOSQ_ERR_SUCCESS; - } - }else{ - /* Check for e.g. foo/bar matching foo/+/# */ - if(topic[0] == 0 - && spos > 0 - && sub[-1] == '+' - && sub[0] == '/' - && sub[1] == '#') - { - *result = true; - return MOSQ_ERR_SUCCESS; - } - - /* There is no match at this point, but is the sub invalid? */ - while(sub[0] != 0){ - if(sub[0] == '#' && sub[1] != 0){ - return MOSQ_ERR_INVAL; - } - spos++; - sub++; - } - - /* Valid input, but no match */ - return MOSQ_ERR_SUCCESS; - } - }else{ - /* sub[spos] == topic[tpos] */ - if(topic[1] == 0){ - /* Check for e.g. foo matching foo/# */ - if(sub[1] == '/' - && sub[2] == '#' - && sub[3] == 0){ - *result = true; - return MOSQ_ERR_SUCCESS; - } - } - spos++; - sub++; - topic++; - if(sub[0] == 0 && topic[0] == 0){ - *result = true; - return MOSQ_ERR_SUCCESS; - }else if(topic[0] == 0 && sub[0] == '+' && sub[1] == 0){ - if(spos > 0 && sub[-1] != '/'){ - return MOSQ_ERR_INVAL; - } - spos++; - sub++; - *result = true; - return MOSQ_ERR_SUCCESS; - } - } - } - if((topic[0] != 0 || sub[0] != 0)){ - *result = false; - } - while(topic[0] != 0){ - if(topic[0] == '+' || topic[0] == '#'){ - return MOSQ_ERR_INVAL; - } - topic++; - } - - return MOSQ_ERR_SUCCESS; -} - -void MQTT::connlost(void *context, char *cause) { - std::cout << "Connection lost: cause: " << cause << std::endl; -} - -void MQTT::delivered(void *context, MQTTClient_deliveryToken dt) { - //std::cout << "Message with token value %d delivery confirmed" << std::endl; -} - -int MQTT::msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message) { - MQTT* mqttClient = static_cast(context); - - bool topic_matches; - for (const auto& sub : mqttClient->subscriptions) { - topic_match(sub.topic.c_str(), topicName, &topic_matches); - if (topic_matches) { - sub.onMsgReceive(topicName, std::string((char *)message->payload, message->payloadlen)); - } - } - return 1; -} - -MQTT::MQTT(const std::string& serverURI) : MQTT(serverURI, 0) {} - -MQTT::MQTT(const std::string& serverURI, int retained_default) { - this->retained_default = retained_default; - - conn_opts = MQTTClient_connectOptions_initializer; - MQTTClient_create(&mqttClient, serverURI.c_str(), "ClientC++-jdj", MQTTCLIENT_PERSISTENCE_NONE, NULL); - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - - MQTTClient_setCallbacks(mqttClient, static_cast(this), MQTT::connlost, MQTT::msgarrvd, MQTT::delivered); -} - -bool MQTT::connect() { - int rc; - - if ((rc = MQTTClient_connect(mqttClient, &conn_opts)) != MQTTCLIENT_SUCCESS) { - std::cout << "[ERROR] MQTT::connect: Connectionn failed with return code: " << rc << std::endl; - return false; - } - - return true; -} - -bool MQTT::last_will(const std::string& willTopic, const std::string& willMessage, int retained) { - if (! is_connected()) { - will_opts = MQTTClient_willOptions_initializer; - will_opts.topicName = willTopic.c_str(); - will_opts.message = willMessage.c_str(); - will_opts.retained = retained; - conn_opts.will = &will_opts; - - return true; - } - - return false; -} - -bool MQTT::is_connected() { - return MQTTClient_isConnected(mqttClient); -} -//TODO QOS -void MQTT::subscribe(const std::string& topic, std::function onMsgReceive) { - subscriptions.emplace_back(topic, onMsgReceive); - MQTTClient_subscribe(mqttClient, topic.c_str(), 0); -} - - -void MQTT::publish(const std::string& topic, std::string message) const { - publish(topic, message, retained_default); -} - -void MQTT::publish(const std::string &topic, std::string message, int retained) const { - const char *msg = message.c_str(); - MQTTClient_publish(mqttClient, topic.c_str(), strlen(msg), (void *) msg, 1, retained, NULL); -} - -MQTT::~MQTT() { - spdlog::trace("Closing mqtt connection '{}'", "TODO tcp://chimaera:1883"); - MQTTClient_disconnect(mqttClient, 10000); - MQTTClient_destroy(&mqttClient); - spdlog::trace("Closed"); - -} diff --git a/src/MQTT.h b/src/MQTT.h deleted file mode 100644 index 5b87766..0000000 --- a/src/MQTT.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// Created by Julian-Steffen Müller on 24.01.20. -// - -#ifndef DECONZ2MQTT_MQTT_H -#define DECONZ2MQTT_MQTT_H - -#include "MQTTClient.h" -#include -#include -#include - -struct MQTT_Topic_Subscription { - std::string topic; - std::function onMsgReceive; - - MQTT_Topic_Subscription(std::string topic, std::function onMsgreceive) : topic(topic), onMsgReceive(onMsgreceive) {} -}; - -class MQTT { -private: - MQTTClient mqttClient; - MQTTClient_connectOptions conn_opts; - MQTTClient_willOptions will_opts; - - int retained_default; - - static void connlost(void *context, char *cause); - - static void delivered(void *context, MQTTClient_deliveryToken dt); - - static int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message); - -public: - MQTT(const std::string& serverURI); - MQTT(const std::string& serverURI, int retained_default); - - - std::vector subscriptions; - bool connect(); - bool is_connected(); - - bool last_will(const std::string& willTopic, const std::string& willMessage, int retained = 1); - - void publish(const std::string& topic, std::string message) const; - void publish(const std::string& topic, std::string message, int retained) const; - - void subscribe(const std::string& topic, std::function onMsgReceive); - - ~MQTT(); - -}; - -#endif //DECONZ2MQTT_MQTT_H diff --git a/src/Version.h b/src/Version.h new file mode 100644 index 0000000..3826061 --- /dev/null +++ b/src/Version.h @@ -0,0 +1,8 @@ +#if !defined(VERSION_H) +#define VERSION_H + +#define MQTTEXPLORER_VERSION_MAJOR 1 +#define MQTTEXPLORER_VERSION_MINOR 0 +#define MQTTEXPLORER_VERSION_PATCH 0 + +#endif // VERSION_H diff --git a/src/main.cpp b/src/main.cpp index 35e8870..9e020f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,19 @@ #include "spdlog/spdlog.h" -#include "MQTT.h" +#include "mqttpp.h" #include #include +#include +#include "Version.h" int main(int argc, const char* argv[]) { - MQTT mqtt("tcp://chimaera:1883"); + if (argc >= 2) { + if (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version")) { + std::cout << "Version: " << MQTTEXPLORER_VERSION_MAJOR << "." << MQTTEXPLORER_VERSION_MINOR << "." << MQTTEXPLORER_VERSION_PATCH << std::endl; + return 0; + } + } + + mqttpp::Client mqtt("tcp://chimaera:1883"); spdlog::info("Establishing mqtt connection to {} on port {}", "chimaera", "1883");