Page 1 of 1

MQTT Keep Alive Interval

Posted: Fri Sep 13, 2024 3:12 pm
by miznick
We're having an issue where the MQTT client disconnect with the error:

Code: Select all

E (55949) coreMQTT: Handling of keep alive failed. Status=MQTTKeepAliveTimeout                                                 
E (55949) coreMQTT: Call to receiveSingleIteration failed. Status=MQTTKeepAliveTimeout                                         
E (55949) coreMQTT: MQTT operation failed with status MQTTKeepAliveTimeout  
Digging into core_mqtt.c, the handleKeepAlive() function looks like this:

Code: Select all

static MQTTStatus_t handleKeepAlive( MQTTContext_t * pContext )
{
    MQTTStatus_t status = MQTTSuccess;
    uint32_t now = 0U;
    uint32_t packetTxTimeoutMs = 0U;

    assert( pContext != NULL );
    assert( pContext->getTime != NULL );

    now = pContext->getTime();

    packetTxTimeoutMs = 1000U * ( uint32_t ) pContext->keepAliveIntervalSec;

    if( PACKET_TX_TIMEOUT_MS < packetTxTimeoutMs )
    {
        packetTxTimeoutMs = PACKET_TX_TIMEOUT_MS;
    }
    packetTxTimeoutMs = 10000;
    /* If keep alive interval is 0, it is disabled. */
    if( pContext->waitingForPingResp == true )
    {
        /* Has time expired? */
        if( calculateElapsedTime( now, pContext->pingReqSendTimeMs ) >
            MQTT_PINGRESP_TIMEOUT_MS )
        {
            status = MQTTKeepAliveTimeout;
        }
    }
    else
    {
        if( ( packetTxTimeoutMs != 0U ) && ( calculateElapsedTime( now, pContext->lastPacketTxTime ) >= packetTxTimeoutMs ) )
        {
            ESP_LOGI("test","txPING %d", packetTxTimeoutMs);
            status = MQTT_Ping( pContext );
        }
        else
        {
            const uint32_t timeElapsed = calculateElapsedTime( now, pContext->lastPacketRxTime );

            if( ( timeElapsed != 0U ) && ( timeElapsed >= PACKET_RX_TIMEOUT_MS ) )
            {
                ESP_LOGI("test","rxPING %d", pContext->lastPacketRxTime);
                status = MQTT_Ping( pContext );
            }
        }
    }

    return status;
}
We added the ESP_LOGI to see when each type of MQTT_Ping() is called, and what we find is that pContext->lastPacketRxTime is always zero. In fact, searching the entire code base we see that lastPacketRxTime is never modified.

Two questions:

1 - Why do we even check for last RX packet? Isn't the rule for MQTT keep alive that the client is responsible for sending a PING regularly otherwise the server closes the connection.

2 - Should lastPacketRxTime be updated somewhere?