fizista / micropython-umqtt.robust2

MIT License
48 stars 6 forks source link

set_last_will not working if only use reconnect without connect first ? #4

Closed tinamore closed 4 years ago

tinamore commented 4 years ago

Describe the bug set_last_will not working if only use reconnect without connect first I use A9G board

There's no guarantee that GPRS connects successfully the first time, so I don't call the connect () function. I just called reconect in the for loop. I am suspicious that reconect () didn't send the Last Will and Testament attached

I disconnected the power from the board but within a few minutes I still didn't see it offline.

To Reproduce Steps to reproduce the behavior:

import utime
from umqtt.robust2 import MQTTClient

def sub_cb(topic, msg, retained, duplicate):
    print((topic, msg, retained, duplicate))

c = MQTTClient("umqtt_client", "localhost")
# Print diagnostic messages when retries/reconnects happens
c.DEBUG = True
# Information whether we store unsent messages with the flag QoS==0 in the queue.
c.KEEP_QOS0 = False
# Option, limits the possibility of only one unique message being queued.
c.NO_QUEUE_DUPS = True
# Limit the number of unsent messages in the queue.
c.MSG_QUEUE_MAX = 2

c.set_callback(sub_cb)

c.set_last_will(topic_pub_availability, "Offline", True, 1) #topic, 'online', retain=True, qos=1

# Connect to server, requesting not to clean session for this
# client. If there was no existing session (False return value
# from connect() method), we perform the initial setup of client
# session - subscribe to needed topics. Afterwards, these
# subscriptions will be stored server-side, and will be persistent,
# (as we use clean_session=False).
#
# TODO: Still exists???
# There can be a problem when a session for a given client exists,
# but doesn't have subscriptions a particular application expects.
# In this case, a session needs to be cleaned first. See
# example_reset_session.py for an obvious way how to do that.
#
# In an actual application, it's up to its developer how to
# manage these issues. One extreme is to have external "provisioning"
# phase, where initial session setup, and any further management of
# a session, is done by external tools. This allows to save resources
# on a small embedded device. Another extreme is to have an application
# to perform auto-setup (e.g., clean session, then re-create session
# on each restart). This example shows mid-line between these 2
# approaches, where initial setup of session is done by application,
# but if anything goes wrong, there's an external tool to clean session.
# if not c.connect(clean_session=False):
#     print("New session being set up")
#     c.subscribe(b"foo_topic")

while 1:
    utime.sleep_ms(500)

    # At this point in the code you must consider how to handle
    # connection errors.  And how often to resume the connection.
    if c.is_conn_issue():
        while c.is_conn_issue():
            # If the connection is successful, the is_conn_issue
            # method will not return a connection error.
            c.reconnect()
        else:
            c.resubscribe()

    c.check_msg() # needed when publish(qos=1), ping(), subscribe()
    c.send_queue()  # needed when using the caching capabilities for unsent messages

c.disconnect()

Details (please complete the following information):

tinamore commented 4 years ago

Hi, I set c.keepalive = 15 # 15s and I call c.ping() every 5 second is OK.

I am wondering code is missing: not auto send ping every keeplive / 3.

fizista commented 4 years ago

The reconnect method is in fact the connect(clean_session=False) method with additions.

And the connect method with cleean_session=False sets "Last Will" correctly. I tested it just now.

You would need to see what messages are displayed on REPL.

Perhaps something else is affecting this problem. From my point of view, everything works.

fizista commented 4 years ago

The programmer is responsible for maintaining the connection. So you have to choose the keep_alive parameters yourself and send a ping to make the connection active.

fizista commented 4 years ago

There are many different strategies for maintaining the connection, and that is why it is on the programmer's side to keep the connection active.

The problem is also under micropython to keep some code in the background to perform some tasks. That's why this library leaves it up to the programmer to choose their own methods to keep the connection active.

tinamore commented 4 years ago

First, I set keepalive = 15s I don't understand why the reconnect for 15s. Then I discovered that robust2 did not ping automatically. Each time will be blocked 1-2 seconds due to the reconnect process but call Ping is very fast. I think you should add in the readme the need to maintain keepAlive with Ping().

Thank you very much for the great lib MQTT for micropython library. I hope it will be stable like mqtt pubsub library in arduino.