aiomqtt icon indicating copy to clipboard operation
aiomqtt copied to clipboard

session persistence with protocol version 5

Open larsclaussen opened this issue 1 year ago • 1 comments

Hi,

Not sure if this is a bug or if I'm doing something wrong here. I'm trying to establish a persistence session with my subscribing client. Using protocol version 3 (protocol=ProtocolVersion.V311) in combination with clean_session=False I see outstanding messages published with QOS 1 being picked up after a reconnect.

Swapping that out for protocol version 5 (protocol=ProtocolVersion.V5) in combination with clean_start, however, does not show the same behavior, no matter if I use clean_start=1, clean_start=2 or clean_start=3. I tested them all because it is not really clear how the docs

clean_start – (MQTT v5.0 only) Set the clean start flag always, never, or only on the first successful connection to the broker.

translate to the values. The persistent session section in the docs refers to the clean_session parameter only.

Could you please let me know what I'm doing wrong or confirm that this is a bug?

client code

def _get_aiomqtt_client(
    clean_session: bool = False, tls_context: ssl.SSLContext | None = None
):
    _id = "worker-client"
    port = settings.MQTT.TCP_PORT

    if tls_context is not None:
        port = settings.MQTT.TLS_PORT

    return aiomqtt.Client(
        hostname=settings.MQTT.HOSTNAME,
        port=port,
        username=settings.MQTT.USERNAME,
        password=settings.MQTT.PASSWORD,
        client_id=_id,
        tls_context=tls_context,
        protocol=ProtocolVersion.V5,
        clean_start=3,  # or 0 | 1 | 2  makes no difference   
        )

version

aiomqtt==1.2.1

Edit

Looking at the paho source code I see

:param bool clean_start: (MQTT v5.0 only) True, False or MQTT_CLEAN_START_FIRST_ONLY

where

MQTT_CLEAN_START_FIRST_ONLY: CleanStartOption = 3

So it's either 0,1 or 3 (gotta love constructs like this).

To make this work you need to create the client like this

def _get_aiomqtt_client(
    clean_session: bool = False, tls_context: ssl.SSLContext | None = None
):
    from paho.mqtt.properties import Properties
    from paho.mqtt.packettypes import PacketTypes 
    properties=Properties(PacketTypes.CONNECT)
    properties.SessionExpiryInterval = 30 * 60 # in seconds

    _id = "worker-client"
    port = settings.MQTT.TCP_PORT

    if tls_context is not None:
        port = settings.MQTT.TLS_PORT

    return aiomqtt.Client(
        hostname=settings.MQTT.HOSTNAME,
        port=port,
        username=settings.MQTT.USERNAME,
        password=settings.MQTT.PASSWORD,
        client_id=_id,
        tls_context=tls_context,
        protocol=ProtocolVersion.V5,
        clean_start=2,
        properties=properties
    )

larsclaussen avatar Feb 14 '24 12:02 larsclaussen

Hi there, let's try to get to the bottom of this together 🙂

paho-mqtt is unfortunately a bit light on documentation. As far as I know, clean_session is a valid argument both for MQTTv3 and MQTTv5. I would leave clean_start at its default for now when we compare the two.

I'm having trouble reproducing this from your description. Could you post a minimal example that's runnable as-is and that shows the difference from your expectation?

empicano avatar Feb 21 '24 21:02 empicano