mlesniew / PicoMQTT

ESP MQTT client and broker library
GNU Lesser General Public License v3.0
255 stars 28 forks source link

Request: Usage example of will topic and payload #10

Closed agri-code closed 1 year ago

agri-code commented 1 year ago

Hello there!

I've been impressed so far with what picoMQTT can do. However, I were unable to get it to send the will topic and payload.

Could you please provide a working example?

agri-code commented 1 year ago

I forgot to mention: I am using PicoMQTT::Client to connect to mosquitto with a will topic and payload. It is unclear to me after reading the code in what order to call .connect(const char * host, uint16_t port, const char * id, const char * user, const char * pass, const char * will_topic, const char * will_message, const size_t will_message_length, uint8_t will_qos, bool will_retain, const bool clean_session, ConnectReturnCode * connect_return_code)

and then .begin() or just connect and omit .begin() altogether and have it .loop() in the main function.

mlesniew commented 1 year ago

Unfortunately, will messages are not fully implemented in the PicoMQTT::Client class yet. They are only supported in its base class, PicoMQTT::BasicClient, which is a simpler MQTT Client, with no auto-reconnects.

I'm planning to add will message support to PicoMQTT::Client and want to add an example on how to use it, but right now you would have to do a bit of hacking to use will messages.

For now if you want to use will messages, you have two options:

I would suggest going with the 2nd option. In that case your code could look more or less like this:

class MyMQTTClient: public PicoMQTT::Client {
public:
void loop() override {
    if (!client.connected()) {
        if (host.isEmpty() || !port) {
            return;
        }

        if (millis() - last_reconnect_attempt < reconnect_interval_millis) {
            return;
        }

        last_reconnect_attempt = millis();

        if (!connect(host.c_str(), port,
                     client_id.isEmpty() ? "" : client_id.c_str(),
                     username.isEmpty() ? nullptr : username.c_str(),
                     password.isEmpty() ? nullptr : password.c_str()),
                     "foo",  // will topic
                     "bar",  // will body
                     3,  // will body length in bytes
                     0,  // will qos
                     false,  // will retain 
                 ) {
            return;
        }

        for (const auto & kv : subscriptions) {
            BasicClient::subscribe(kv.first.c_str());
        }
    }

    BasicClient::loop();
}

};
agri-code commented 1 year ago

Yeah, that's the thing... I absolutely suck at C/C++ and have a chronic lack of time to dig into anything deeper than very shallow waters these days. I'd appreciate it if you could make time to implement this and, if humanely possible, a the QOS level 2

I'll make it worth your time

mlesniew commented 1 year ago

Will messages for clients are implemented in the latest release, there's an example in the readme.

I don't plan adding support for QoS level 2 for now. This would require the messages to be stored in RAM until they're full confirmed as received by the broker. This would complicate the code significantly and increase memory usage.