How to set MQTT last will message properly
The Last will and testament feature requires to follow some rules.
Call client.will_set
before you connect
Put call to will_set
before client.connect
.
client = mqtt.Client()
client.will_set("stack/clientstatus", "LOST_CONNECTION", 0, False)
client.connect(host, port, timeout)
Calling will_set
after connect did not work for me.
Only last client.will_set
counts
Trying to use will_set
multiple times is possible, but only the last one will be effective, previous ones will be ignored.
Let client.disconnect
to complete
The client.disconnect
is actually request to send out the "DISCONNECT" message to the broker.
As the messages are sent asynchronously, it is possible, that your program ends sooner, then is the "DISCONNECT" message completed.
Use client.loop_*()
after client.disconnect
This shall allow the client to complete the process of sending the "DISCONNECT" message out.
Following combinations worked for me:
loop_start()
-> loop_stop()
loop_start()
-> loop_forever()
(it completes after sending DISCONNECT message)
I did not experiment with other combinations.
From those option, the first one seems better to me (keeping loop_start
paired with loop_stop
). The second option might be simply wrong.
My working code:
import paho.mqtt.client as mqtt
host = "test.mosquitto.org"
port = 1883
timeout = 10
client = mqtt.Client()
client.will_set("stack/clientstatus", "LOST_CONNECTION", 0, False)
client.connect(host, port, timeout)
client.publish("stack/clientstatus", "ON-LINE")
client.loop_start()
for msg in ["msg1", "msg2", "msg3"]:
client.publish("stack/message", msg)
print msg
client.publish("stack/clientstatus", "OFF-LINE")
client.disconnect()
client.loop_stop() # waits, until DISCONNECT message is sent out
print "Now I am done."
Not reliable methods (sleep
, adding on_disconnect
)
Adding time.sleep
might help, but in other situation (not reliable connection) could fail.
Adding client.on_disconnect = on_disconnect
did not help in my case as it seems, this callback is processed asynchronously and does not block the client.disconnect
call.