Version 1.0

This commit is contained in:
2020-07-19 14:47:55 +02:00
parent 67300f1c10
commit 17d440e1e2
8 changed files with 28 additions and 291 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
build build
.clangd
.vscode

View File

@@ -2,18 +2,17 @@ cmake_minimum_required(VERSION 3.10)
project(mqttExplorer) project(mqttExplorer)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS true)
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
#PAHO-MQTT-C Library include_directories("/usr/local/include")
#USUALLY INSTALLED TO /usr/local/include /usr/local/lib and /usr/local/bin include_directories("/usr/local/include/mqttpp-0.1")
include_directories(/usr/local/include) link_directories("/usr/local/lib/mqttpp-0.1")
link_directories(/usr/local/lib)
set(LIBS ${LIBS} paho-mqtt3cs)
find_package(spdlog CONFIG REQUIRED) 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) install(TARGETS mqttExplorer DESTINATION bin)

Binary file not shown.

Binary file not shown.

View File

@@ -1,227 +0,0 @@
//
// Created by Julian-Steffen Müller on 24.01.20.
//
#include <iostream>
#include "MQTT.h"
#include "string.h"
#include <string>
#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<MQTT *>(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<void*>(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<void(const char*, const std::string&)> 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");
}

View File

@@ -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 <functional>
#include <vector>
#include<string>
struct MQTT_Topic_Subscription {
std::string topic;
std::function<void(const char*, const std::string& )> onMsgReceive;
MQTT_Topic_Subscription(std::string topic, std::function<void(const char*, std::string)> 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<MQTT_Topic_Subscription> 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<void(const char*, const std::string&)> onMsgReceive);
~MQTT();
};
#endif //DECONZ2MQTT_MQTT_H

8
src/Version.h Normal file
View File

@@ -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

View File

@@ -1,10 +1,19 @@
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include "MQTT.h" #include "mqttpp.h"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
#include <cstring>
#include "Version.h"
int main(int argc, const char* argv[]) { 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"); spdlog::info("Establishing mqtt connection to {} on port {}", "chimaera", "1883");