hirotakaster / MQTT

MQTT for Photon, Spark Core
Other
216 stars 118 forks source link

QoS 2 eventually exceeded timeout and disconnecting #86

Closed hangyao closed 3 years ago

hangyao commented 3 years ago

I run a modified variant of mqqtqostest.ino on Particle Photon with publishing messages every 5 seconds. It runs for a while and eventually disconnects.

Here is the output on my Mosquitto broker:

............
1600958531: Received PUBLISH from sparkclient (d0, q2, r0, m50, 'outTopic/message', ... (64 bytes))
1600958531: Sending PUBREC to sparkclient (m50, rc0)
1600958536: Received PUBREL from sparkclient (Mid: 32)
1600958536: Sending PUBCOMP to sparkclient (m32)
1600958559: Client sparkclient has exceeded timeout, disconnecting.

And here the output on Photon Serial Monitor:

............
Message Id:62
Ack Message Id:24
Message Id:64
Message Id:66
Message Id:0

I noticed that the Message ID keeps increasing until 66, then it goes back to 0. It seems like it leads to the timeout and disconnecting of Photon client.

Here are my setup() and loop() functions of the Photon firmware. Other parts are the same as mqqtqostest.ino` example.

void setup() {
    Serial.begin(9600);
    RGB.control(true);

    // connect to the server
    client.connect("sparkclient");

    // add qos callback. If don't add qoscallback, ACK message from MQTT server is ignored.
    client.addQosCallback(qoscallback);
}

void loop() {
    if (client.isConnected()) {
        client.loop();

        // get the messageid from parameter at 4.
        uint16_t messageid;

        // QOS=2
        client.publish("outTopic/message", msg, MQTT::QOS2, &messageid);
        Serial.println(messageid);

        // save QoS2 message id as global parameter.
        qos2messageid = messageid;

        delay(5000);
    }
}
hirotakaster commented 3 years ago

hi @hangyao ,

on my Photon test, QoS2 message can send over 2,000 now with my mosquitto and mqtt.eclipse.org server. 5 * 60 = 300sec is TCP default timeout. Maybe your WiFi router or mosquitto server environment is affected. Your application could work on the open MQTT server(mqtt.eclipse.org)?

hangyao commented 3 years ago

Yes, I tried on mqtt.eclipse.org:1883 and it stops at the same point.

And by the way, QoS 0 works just fine on either way and can goes forever, and the message ID is always 0 for QoS 0.

hi @hangyao ,

on my Photon test, QoS2 message can send over 2,000 now with my mosquitto and mqtt.eclipse.org server. 5 * 60 = 300sec is TCP default timeout. Maybe your WiFi router or mosquitto server environment is affected. Your application could work on the open MQTT server(mqtt.eclipse.org)?

hirotakaster commented 3 years ago

oh, it's weird. Okay, please show your stop all source code with mqtt.eclipse.org server. My photon latest firmware and MQTT QoS sample source code don't get your case, I will try same source code on my Photon.

hangyao commented 3 years ago

Here is the full source code:

// This #include statement was automatically added by the Particle IDE.
#include "MQTT.h"

void callback(char* topic, byte* payload, unsigned int length);

// Use local IP address and MQTT port
MQTT client("mqtt.eclipse.org", 1883, callback);

// for QoS2 MQTTPUBREL message.
// this messageid maybe have store list or array structure.
uint16_t qos2messageid = 0;

// recieve message
void callback(char* topic, byte* payload, unsigned int length) {
    delay(1000);
}

// QOS ack callback.
// if application use QOS1 or QOS2, MQTT server sendback ack message id.
void qoscallback(unsigned int messageid) {
    Serial.print("Ack Message Id:");
    Serial.println(messageid);
}

void setup() {
    Serial.begin(9600);
    RGB.control(true);

    // connect to the server
    client.connect("sparkclient");

    // add qos callback. If don't add qoscallback, ACK message from MQTT server is ignored.
    client.addQosCallback(qoscallback);
}

void loop() {
    if (client.isConnected()) {
        client.loop();

        // get the messageid from parameter at 4.
        uint16_t messageid;

        // QOS=2
        client.publish("outTopic/message", "Hello World", MQTT::QOS2, &messageid);
        Serial.println(messageid);

        // save QoS2 message id as global parameter.
        qos2messageid = messageid;

        // Wait for 5 seconds
        delay(5000);
    }
}
hirotakaster commented 3 years ago

this code works on my Particle/Argon over 1 hour. your wifi network environment (or wifi router) might be a problem, you could check another network. and same client id will disconnect from other user, client.connect("sparkclient"); change another user id is better.

hangyao commented 3 years ago

Thank you for verifying it!