MQTT Keep Alive Interval
Posted: Fri Sep 13, 2024 3:12 pm
We're having an issue where the MQTT client disconnect with the error:
Digging into core_mqtt.c, the handleKeepAlive() function looks like this:
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?
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
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;
}
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?