Aws-iot-device-sdk-python-v2: AWS IOT MQTT with Persistent Session = True but subscription failed

Created on 31 May 2020  ·  4Comments  ·  Source: aws/aws-iot-device-sdk-python-v2

Dear All,

While experimenting with AWS IOT MQTT with Persistent Session I found that Broker returns 'session_present = True' in reply to connection request having 'clean_session = False'.
Which is expected as I reconnected within 60 mins as specified by AWS Documentation ( practically it was less than 5 mins )

Issue :
As per the theory, if 'session_present = True' then the broker stores ass previous session's info hence no need to subscribe to topics again.
But if I skip the step of subscribing to the topic then no messages received.
Is it the obvious behavior ? do I need to unsubscribe even though 'session_present = True' ?

I am using aws-iot-device-sdk-python-v2

def conenct_mqtt(mqtt_connection):
    connect_future = mqtt_connection.connect()

    excep_count = 0
    while True:
        print(f"[{datetime.now()}]Connecting......")
        try:
            # Future.result() waits until a result is available
            result = connect_future.result(timeout=30)
            print(f"Connected! session persistent = {result['session_present']}")
            return result['session_present']

        except Exception as exc:
            print(f"[{datetime.now()}]Error while connecting {exc}")
            time.sleep(10)
            excep_count=excep_count+1
            if excep_count > 5 :
                print(f"[{datetime.now()}]Exiting Script.....")
                quit()
bug guidance needs-triage

Most helpful comment

Hi @GauravPatni

Please try:

   if not is_session_persistent:
        XXX
   else:
        mqtt_connection.on_message(on_message_received) #register your callback
        print("-----------Session is Persistent---------")

You connection is connected, but you still need to register your callback on the _Connection_ object to received the message, via on_message.

All 4 comments

Hi,
Thank you for reaching out. I have tested it and the Persistent Session works for me.
In the pubsub.py sample, if the connection is lost and comes back, the mqtt_conneciton continues receiving message. But you need to register you callback on the _Connection_ object to received the message.
For example, if you create another _Connection_ object, with the 'session_present = True' as a connection result, you will need to call on_message to set the callback. Then you can receive the incoming message via the callback you set.
Thank you!

hi @TingDaoK
Thanks for your help. But unfortunately, still, i am not able to solve the issue.
could you please look into the following code to figure out what's the issue?

my steps :
run subscribe script
run publish script
// messages received on subscribe script
now terminate both the scripts
wait for a min or more
run subscribe script
// connection future result returns .... result['session_present'] = True. Hence subscribe loop is skipped
run publish script
// Issue: no messages received on subscribe script

def conenct_mqtt(mqtt_connection):
    connect_future = mqtt_connection.connect()

    excep_count = 0
    while True:
        print(f"[{datetime.now()}]Connecting......")
        try:
            # Future.result() waits until a result is available
            result = connect_future.result(timeout=30)
            print(f"[{datetime.now()}]Connected! session persistent = {result['session_present']}")
            return result['session_present']

        except Exception as exc:
            print(f"[{datetime.now()}]Error while connecting {exc}")
            time.sleep(10)
            excep_count=excep_count+1
            if excep_count > 5 :
                print(f"[{datetime.now()}]Exiting Script.....")
                quit()

if __name__ == '__main__':
    # Spin up resources
    event_loop_group = io.EventLoopGroup(1)
    host_resolver = io.DefaultHostResolver(event_loop_group)
    client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)


    mqtt_connection = mqtt_connection_builder.mtls_from_path(
        endpoint=host,
        cert_filepath=certificatePath,
        pri_key_filepath=privateKeyPath,
        client_bootstrap=client_bootstrap,
        ca_filepath=rootCAPath,
        on_connection_interrupted=on_connection_interrupted,
        on_connection_resumed=on_connection_resumed,
        client_id=clientId,
        clean_session=False, # set as persistent sessions
        keep_alive_secs=60, # 1 min as any data communication or PINGREQ . x1.5 to detect disconenct
        reconnect_min_timeout_secs=2,
        reconnect_max_timeout_secs =300,
        ping_timeout_ms = 10000, # wait for 6 secs for ping response
        )

    print(f"[{datetime.now()}]Connecting with client ID '{clientId}'...")
    is_session_persistent = conenct_mqtt(mqtt_connection)

    # subscribe to topics only if previous session was lost 
    if not is_session_persistent:
        topic_index = 0
        excep_count = 0
        while topic_index < 2:
            # Subscribe
            topic = topic_list[topic_index]
            print(f"[{datetime.now()}]Subscribing to topic '{topic}'...")
            subscribe_future, packet_id = mqtt_connection.subscribe(
                topic=topic,
                qos=mqtt.QoS.AT_LEAST_ONCE,
                callback=on_message_received)


            try:
                subscribe_result = subscribe_future.result()
                print(f"[{datetime.now()}]Subscribed with {str(subscribe_result['qos'])}")
                topic_index+=1
                excep_count = 0
            except Exception as exc:
                print(f"Error:Subscribe: {exc}")
                excep_count+=1
                if excep_count > 3 :
                    print(f"[{datetime.now()}]Exiting Script.....")
                    quit()
                time.sleep(10)
    else:
        print("-----------Session is Persistent---------")




    # Wait for all messages to be received.
    # This waits forever if count was set to 0.
    if max_count != 0 and not received_all_event.is_set():
        print("Waiting for all messages to be received...")

    received_all_event.wait()
    print("{} message(s) received.".format(received_count))

Hi @GauravPatni

Please try:

   if not is_session_persistent:
        XXX
   else:
        mqtt_connection.on_message(on_message_received) #register your callback
        print("-----------Session is Persistent---------")

You connection is connected, but you still need to register your callback on the _Connection_ object to received the message, via on_message.

Thanks

Hi @GauravPatni

Please try:

   if not is_session_persistent:
        XXX
   else:
        mqtt_connection.on_message(on_message_received) #register your callback
        print("-----------Session is Persistent---------")

You connection is connected, but you still need to register your callback on the _Connection_ object to received the message, via on_message.

Thanks @TingDaoK

after adding
mqtt_connection.on_message(on_message_received) #register your callback
issue resolved !!

Once again thanks for quick reply !!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Sanrro10 picture Sanrro10  ·  16Comments

satay99 picture satay99  ·  6Comments

banuprathap picture banuprathap  ·  10Comments

qcabrol picture qcabrol  ·  8Comments

mkozjak picture mkozjak  ·  8Comments