边缘计算 | paho: qos | callbacks | loop
qos (quality of service)
The QOS levels are a way of guaranteeing message delivery and they refer to the connection between a broker and a client.In this tutorial we will look in detail at the message flow when publishing using all three QOS levels.
QOS 0 – Once (not guaranteed).
This is the fastest method and requires only 1 message. It is also the most unreliable transfer mode.The message is not stored on the sender, and is not acknowledged.The message will be delivered only once, or not at all.Once the message has been sent by the client it is deleted from the outbound message queue.Therefore with this QOS level there is no possibility of duplicate messages.
QOS 1 – At Least Once (guaranteed).
This level guarantees that the message will be delivered at least once, but may be delivered more than once. Publishing with QOS of 1 requires 2 messages.
The sender sends a message and waits for an acknowledgement (PUBACK).
If it receives an acknowledgement then it notifies the client app, and deletes the message from the outbound queue.
If it doesn’t receive an acknowledgement it will resend the message with the DUP flag set (Duplicate Flag).
The message will continue to be resent at regular intervals, until the sender receives an acknowledgement.
QOS 2 – Only Once (guaranteed).
This level guarantees that the message will be delivered only once. This is the slowest method as it requires 4 messages.
The sender sends a message and waits for an acknowledgement (PUBREC)
The receiver sends a PUBREC message
If the sender doesn’t receive an acknowledgement ( PUBREC) it will resend the message with the DUP flag set.
When the sender receives an acknowledgement message PUBREC it then sends a message release message (PUBREL). The message can be deleted from the queue.
If the receiver doesn’t receive the PUBREL it will resend the PUBREC message
When the receiver receives the PUBREL message it can now forward the message onto any subscribers.
The receiver then send a publish complete (PUBCOMP).
If the sender doesn’t receive the PUBCOMP message it will resend the PUBREL message.
When the sender receives the PUBCOMP the process is complete and it can delete the message from the outbound queue, and also the message state.
Client to Client or End to End QOS
The Quality of service between two clients connected to a broker is determined by the QOS of the published message,and the QOS of the subscribing client.When a client subscribes to a broker with a QOS it is effectively instructing the broker to publish messages to it, with that QOS.The overall QOS is always equal to the lowest QOS of the publish or subscribe, as shown in the table below
Usually, If you want to try and ensure that the subscriber gets a message, you need to publish with a quality of service of 1 or 2.
13 kinds of callbacks
On the receive side it looks at the messages, and depending on the message type, it will trigger the appropriate callback function.For example if it sees a CONNACK message it triggers the on_connect() callback. there are 13 kinds of callbacks, as follows
common parameter description
the client instance for current callback
the private user data as set in Client() or user_data_set()
result code, for connect situation, the value of rc indicates sucess or not, as follow
0: Connection successful 1: Connection refused - incorrect protocol version 2: Connection refused - invalid client identifier 3: Connection refused - server unavailable 4: Connection refused - bad username or password 5: Connection refused - not authorised 6-255: Currently unused.
import paho.mqtt.client as mqtt
mqttc = mqtt.Client()
on_connect(client, userdata, flags, rc)
Called when the broker responds to our connection request.
response flags sent by the broker,flags is a dict that contains response flags from the broker,flags['session present'] - this flag is useful for clients that are using clean session set to 0 only. If a client with clean session=0, that reconnects to a broker that it has previously connected to, this flag indicates whether the broker still has the session information for the client. If 1, the session still exists.
def on_connect(client, userdata, flags, rc):
print("Connection returned result: "+connack_string(rc))
mqttc.on_connect = on_connect
on_disconnect(client, userdata, rc)
Called when the client disconnects from the broker.The rc parameter indicates the disconnection state. If MQTT_ERR_SUCCESS (0), the callback was called in response to a disconnect() call. If any other value the disconnection was unexpected, such as might be caused by a network error.
def on_disconnect(client, userdata, rc):
if rc != 0:
mqttc.on_disconnect = on_disconnect
on_message(client, userdata, message)
Called when a message has been received on a topic that the client subscribes to and the message does not match an existing topic filter callback. Use message_callback_add() to define a callback that will be called for specific topic filters. on_message will serve as fallback when none matched.
an instance of MQTTMessage. This is a class with members topic, payload, qos, retain.
def on_message(client, userdata, message):
print("Received message '" + str(message.payload) + "' on topic '"
+ message.topic + "' with QoS " + str(message.qos))
mqttc.on_message = on_message
This function allows you to define callbacks that handle incoming messages for specific subscription filters, including with wildcards. This lets you, for example, subscribe to sensors/# and have one callback to handle sensors/temperature and another to handle sensors/humidity.
Remove a topic/subscription specific callback previously registered using message_callback_add().
on_publish(client, userdata, mid)
Called when a message that was to be sent using the publish() call has completed transmission to the broker. For messages with QoS levels 1 and 2, this means that the appropriate handshakes have completed. For QoS 0, this simply means that the message has left the client. The mid variable matches the mid variable returned from the corresponding publish() call, to allow outgoing messages to be tracked.
This callback is important because even if the publish() call returns success, it does not always mean that the message has been sent.
on_subscribe(client, userdata, mid, granted_qos)
Called when the broker responds to a subscribe request. The mid variable matches the mid variable returned from the corresponding subscribe() call. The granted_qos variable is a list of integers that give the QoS level the broker has granted for each of the different subscription requests.
The mid (message ID) value can be compared with the one returned by the function call to check for successful subscription requests.You would use the mid values when checking on multiple subscriptions as some might fail and others succeed, Also note the result value of 0 which is a success code (MQTT_ERR_SUCCESS)
on_unsubscribe(client, userdata, mid)
Called when the broker responds to an unsubscribe request. The mid variable matches the mid variable returned from the corresponding unsubscribe() call.
on_log(client, userdata, level, buf)
Called when the client has log information. Define to allow debugging. The level variable gives the severity of the message and will be one of MQTT_LOG_INFO, MQTT_LOG_NOTICE, MQTT_LOG_WARNING, MQTT_LOG_ERR, and MQTT_LOG_DEBUG. The message itself is in buf.
This may be used at the same time as the standard Python logging, which can be enabled via the enable_logger method.
on_socket_open(client, userdata, sock)
Called when the socket has been opened. Use this to register the socket with an external event loop for reading.
on_socket_close(client, userdata, sock)
Called when the socket is about to be closed. Use this to unregister a socket from an external event loop for reading.
on_socket_register_write(client, userdata, sock)
Called when a write operation to the socket failed because it would have blocked, e.g. output buffer full. Use this to register the socket with an external event loop for writing.
on_socket_unregister_write(client, userdata, sock)
Called when a write operation to the socket succeeded after it had previously failed. Use this to unregister the socket from an external event loop for writing.
The Paho Python client provides three methods: loop_start()、loop_forever() and loop().
The loop_start() starts a new thread, that calls the loop method at regular intervals for you. It also handles re-connects automatically.The loop_forever() method blocks the program, and is useful when the program must run indefinitely.
Loop_start starts a loop in another thread and lets the main thread continue if you need to do other things in the main thread then it is important that it doesn’t end.To accomplish this you need to use your own wait loop.The loop_forever call blocks the main thread and so it will never terminate.The loop_forever call must be placed at the very end of the main script code as it doesn’t progress beyond it.