hirotakaster / MQTT

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

Mqtt Fails to connect #66

Open fcabrera23 opened 7 years ago

fcabrera23 commented 7 years ago

Sometimes the client fails to connect for some time. I have to reset Electron so that the entire connection restarts ( i've checked and the internet connectivity is ok and even send a mqtt.disconnect() before trying a connection). Could it be clean session needed? Thanks

fcabrera23 commented 7 years ago

Parameters :

char server[] = "m13.cloudmqtt.com"; // Servevor Mqtt Nuevo int portMqtt = 18509; char clientId ="73122"; char username = "73122"; char* password= "dfk;lfsdg"; MQTT mqttClient(server, portMqtt,30,callbackMQTT);

Basically this is my loop

 if (Cellular.ready())
{
    digitalWrite(ledGPRS,0);
    attempts = 0;
    if (mqttClient.isConnected()) {
        mqttClient.loop();
 } else {
        Serial.println("Connect to the MQTT server!!");
        mqttClient.connect(clientId,username,password);
        if (mqttClient.isConnected()) {
            Serial.println("Connected");
            mqttClient.addQosCallback(qoscallback);
            mqttClient.publish("reconnections", celu.imei);
        }
    }
}
else
{
    digitalWrite(ledGPRS,1);
    if(attempts > 10){ // Si ya probe 10 (mas de 50 minutos intentando la conexion) veces la conexion y no tuve exito
        System.reset();
    }

    if ((millis() - lastConnect) >= CONNECT_TIMEOUT)
    {
        if(bomba_encendida == APAGADO) // Si la bomab esta desconectada
        {
            Cellular.disconnect();
            Cellular.off();
            delay(5000);
            debug < 1 ? debug=0:Serial.println("Intento conectar modem celular.");
            Cellular.on();
            Cellular.connect();
            lastConnect = millis();
            attempts++;
        }
    }
}

Sometimes it connects, but if reset it, when trying again , won't connect again

I was able to get the log from CloudMqtt:

1502718718: New connection from 179.29.45.169 on port 18509. 1502718726: New connection from 179.29.45.169 on port 18509. 1502718734: New connection from 179.29.45.169 on port 18509. 1502718747: New connection from 179.29.45.169 on port 18509. 1502718754: New connection from 179.29.45.169 on port 18509. 1502718762: New connection from 179.29.45.169 on port 18509. 1502718770: New connection from 179.29.45.169 on port 18509. 1502718778: New connection from 179.29.45.169 on port 18509. 1502718786: New connection from 179.29.45.169 on port 18509. 1502718793: New connection from 179.29.45.169 on port 18509. 1502718801: New connection from 179.29.45.169 on port 18509. 1502718809: New connection from 179.29.45.169 on port 18509. 1502718817: New connection from 179.29.45.169 on port 18509. 1502718825: New connection from 179.29.45.169 on port 18509. 1502718858: New connection from 179.29.45.169 on port 18509. 1502718991: New connection from 179.29.45.169 on port 18509. 1502719150: New connection from 179.29.45.169 on port 18509.

imomo0 commented 7 years ago

I also have this issue running the example mqtttest.ino on the Photon. Could the issue be on the TCPClient lib?

hirotakaster commented 6 years ago

@imomo0 Update and try new firmware version.

leafgarden commented 3 years ago

I had a similar issue when dealing with flaky WiFi connections and had to implement a write timeout in the library, this seems to solve the problem so far. I based my changes off an older version so would need to re-port it before doing a pull request. If this is useful to someone I can try to port it sooner so they can test my changes. If someone else wants to do the port here are some of the changes I did:

I replaced all _client.write(...) with this:

bool MQTT::writeBuffer(const uint8_t *b, size_t s) {
    if ( timeout < 0 ) {
        return s != _client.write(b,s);
    }
    size_t ptr = 0;
    system_tick_t start =  millis();
    _client.clearWriteError();
    long tout = timeout;
    while (ptr < s && tout >= 0) {
        size_t rlen = _client.write(&b[ptr],s-ptr,tout);
        if (_client.getWriteError() != 0 ) {
            break;
        }
        ptr +=rlen;
        tout = (system_tick_t)timeout+(system_tick_t)start-(system_tick_t)millis();
    }
    if ( ptr != s ) {
        _client.stop();
        return false;
    }
    return true;
}

This now returns true/false so the MQTT::write(..) needs to check for true instead of comparing the length.

I added a setter for timeout and defaulted it to -1 so the behavior is not changed if you don't set a timeout.

I allow for a timeout of 0 which is truly non blocking but don't think it is useful, you need to use a more complex Async stye library if you want pure non blocking.

My testing was done with a timeout of 5000 (5 seconds)

NOTE: When adding timeout to the TCPClient.write you need that loop given it will return even when only part of the data is written.