2016-06-21 10 views
2

Ich versuche, einen einfachen MQTT-Client für meine Home-Anwendung zu erstellen, und ich benutze libmosquittopp (das ist C++ - Version von libmosquitto).
Es gibt nicht viel Dokumentation für diese Bibliothek, aber ich fand 2 Beispiele (here und here), die mir geholfen haben, einen Code für meine "MQTTWrapper" -Klasse zu erstellen.libmosquittopp - Beispiel-Client hängt an der Methode loop_stop()

Hier ist mein Code:

MQTTWrapper.h:

#pragma once 

#include <mosquittopp.h> 
#include <string> 

class MQTTWrapper : public mosqpp::mosquittopp 
{ 
public: 
    MQTTWrapper(const char* id, const char* host_, int port_); 
    virtual ~MQTTWrapper(); 

    void myPublish(std::string topic, std::string value); 
private: 
    void on_connect(int rc); 
    void on_publish(int mid); 

    std::string host; 
    int port; 
}; 

MQTTWrapper.cpp

#include "MQTTWrapper.h" 

#include <iostream> 

MQTTWrapper::MQTTWrapper(const char* id, const char* host_, int port_) : 
    mosquittopp(id), host(host_), port(port_) 
{ 
    mosqpp::lib_init(); 

    int keepalive = 10; 
    if (username_pw_set("sampleuser", "samplepass") != MOSQ_ERR_SUCCESS) { 
     std::cout << "setting passwd failed" << std::endl; 
    } 
    connect_async(host.c_str(), port, keepalive); 
    if (loop_start() != MOSQ_ERR_SUCCESS) { 
     std::cout << "loop_start failed" << std::endl; 
    } 
} 

MQTTWrapper::~MQTTWrapper() 
{ 
    std::cout << "1" << std::endl; 
    if (loop_stop() != MOSQ_ERR_SUCCESS) { 
     std::cout << "loop_stop failed" << std::endl; 
    } 
    std::cout << "2" << std::endl; 
    mosqpp::lib_cleanup(); 
    std::cout << "3" << std::endl; 
} 

void MQTTWrapper::on_connect(int rc) 
{ 
    std::cout << "Connected with code " << rc << "." << std::endl; 
} 

void MQTTWrapper::myPublish(std::string topic, std::string value) { 
    int ret = publish(NULL, topic.c_str(), value.size(), value.c_str(), 1, false); 
    if (ret != MOSQ_ERR_SUCCESS) { 
     std::cout << "Sending failed." << std::endl; 
    } 
} 

void MQTTWrapper::on_publish(int mid) { 
    std::cout << "Published message with id: " << mid << std::endl; 
} 

und meine main():

#include <iostream> 
#include <string> 
#include "MQTTWrapper.h" 

int main(int argc, char *argv[]) 
{ 
    MQTTWrapper* mqtt; 
    mqtt = new MQTTWrapper("Lewiatan IoT", "my.cloudmqtt.host", 12345); 

    std::string value("Test123"); 
    mqtt->myPublish("sensors/temp", value); 

    std::cout << "about to delete mqtt" << std::endl; 
    delete mqtt; 
    std::cout << "mqtt deleted" << std::endl; 
    return 0; 
} 

Leider so viel für Code.

Mein Problem ist, dass, wenn ich es kompilieren und ausführen - hängt meine Anwendung unendlich (ich wartete nur 9 Minuten) in MQTTWrapper Destruktor auf loop_stop() -Methode.
Getestet mit libmosquittopp 1.4.8 (debian-Paket) und dann nach dem Entfernen mit Version 1.4.9 von github.

loop_start() und loop_stop(bool force=false) sollten einen separaten Thread starten/stoppen, der Messaging behandelt.

Ich habe es mit Zwangsstopp (loop_stop(true)) getestet, aber auf diese Weise stoppt meine Anwendung und veröffentlicht keine Daten. loop_stop() andererseits veröffentlicht die Daten, hält dann aber an.

Konsolenausgabe (make && ./executable):

g++ -c MQTTWrapper.cpp 
g++ -c main.cpp 
g++ -o executable main.o MQTTWrapper.o -lmosquittopp 
about to delete mqtt 
1 
Connected with code 0. 
Published message with id: 1 
(here it hangs infinitely...) 

Meine Frage:
Warum diese loop_stop() hängt und wie man es beheben?

(alle Unterlagen/tutorial/example geschätzt)

Antwort

2

Versuchen disconnect() vor loop_stop() nennen. Sie sollten auch bedenken, dass Sie dies effektiv zu tun:

connect_async(); 
loop_start(); 
loop_stop(); 

Der Kunde nicht einmal Gelegenheit gehabt haben können, zu verbinden, noch der Thread tatsächlich gestartet werden, bevor Sie es sagen zu stoppen.

Es ist eine Überlegung wert, Aktionen in den Callbacks ausgeführt wird:

on_connect -> call publish 
on_publish -> call disconnect 
+0

Es funktionierte, als ich hinzugefügt 'disconnect()' auf 'on_publish()'. Vielen Dank. Kannst du bitte etwas über diese "Arbeitsweise" mit Callback schreiben? Ich meine - schlagen Sie vor, dass ich jedes Mal, wenn ich Daten veröffentlichen möchte, wieder Verbindung aufbauen sollte? Es sollte einen besseren Ort geben, um disconnect() als in on_publish ... – lewiatan

+0

aufzurufen. In Ihrem Code scheint es so, als wollten Sie sich verbinden, veröffentlichen, sobald die Nachricht veröffentlicht wurde, trennen Sie sie. Ich habe diesen Anwendungsfall angesprochen. Wenn Sie fortlaufend publizieren möchten, dann haben Sie Recht, dass die Trennung in on_publish eine schlechte Idee wäre. – ralight

+0

@lewiatan Ich glaube, das beantwortet Ihre Frage nicht wirklich. Es ist nur ein Stopplückenbeispiel.Für alle mosquitto c/C++ Beispiele erwartet der Benutzer, dass er die Verbindung trennt() nach einer Veröffentlichung, die nicht fair ist, wie Sie bereits geantwortet haben. Könnte es offen gelassen haben. – Kiran