Search code examples
pythoncallbackglobal-variablespahouser-data

Paho updating userdata from on_message callback


Basically, I want my userdata to act as a global flag that gets read and updated between successive executions of the on_message() callback. I wrote and ran the following script:

import paho.mqtt.client as mqtt
MQTT_SERVER = "broker.hivemq.com"
MQTT_TOPIC = "IvanHu"

# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe(MQTT_TOPIC)
    
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    print(userdata, end = '')
    print(" message received.")
    userdata += 1
    user_data_set(client_userdata)

client_userdata = 1

client = mqtt.Client(userdata=client_userdata)
client.on_connect = on_connect
client.on_message = on_message
client.connect(MQTT_SERVER, 1883, 60)

client.loop_forever()

I then published to the topic IvanHu 4 times. I expect the output of my python paho script to be the following:

Connected with result code 0
1 message received.
2 message received.
3 message received.
4 message received.

However, this was what I got instead:

Connected with result code 0
1 message received.
1 message received.
1 message received.
1 message received.

Evidently, the variable client_userdata never got updated in successive on_message() calls. What is the correct way to update this variable?


Solution

  • I couldn't figure out a way to satisfy my requirement using the userdata approach, but I was able to do so with the global variables approach. Here's the working script:

    import paho.mqtt.client as mqtt
    MQTT_SERVER = "broker.hivemq.com"
    MQTT_TOPIC = "IvanHu"
    
    # The callback for when the client receives a CONNACK response from the server.
    def on_connect(client, userdata, flags, rc):
        print("Connected with result code "+str(rc))
        client.subscribe(MQTT_TOPIC)
        
    # The callback for when a PUBLISH message is received from the server.
    def on_message(client, userdata, msg):
        global client_userdata
        print(client_userdata, end = '')
        print(" message received.")
        client_userdata += 1
    
    client_userdata = 1
    
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(MQTT_SERVER, 1883, 60)
    
    client.loop_forever()
    

    Output:

    Connected with result code 0
    1 message received.
    2 message received.
    3 message received.
    4 message received.
    

    The "global variables" approach doesn't use the userdata sent to MQTT broker, but instead increments "locally" the value of the variable. It counts locally the number of times was received the "on_message" callback. Adding a print to display the "userdata" variable as received from MQTT broker will show that its value is always none since never defined in the MQTT client definition or set after its creation.