Andrzej
Andrzej

Reputation: 1

paho.mqtt - getting msg.payload to be printed outside of on_message function

I have below simple code. I'd like to be able to print var form on_message outside of it, but if I put my print(msg.payload) outside of loop is obviously doesn't work, but as loop_forever initializes the function on_message, having print(msg.payload) within loop doesn't work neither (as the function is not initialized.

mybuffer = ''

def on_subscribe(client, userdata, mid, granted_qos):
    print('Subscribed')

def on_message(client, userdata, msg):
    mybuffer = str(msg.payload)
    print('on_message: '+ mybuffer)

client = paho.Client()
client.on_subscribe = on_subscribe
client.on_message = on_message
client.connect('broker', 1883)    
client.subscribe('/andrzej/sensorki')

client.loop_forever()

print(mybuffer)

Upvotes: 0

Views: 2440

Answers (1)

blp
blp

Reputation: 608

There are two problems with your code (which ralight and hardlib have alluded to). First, the program never exits loop_forever() and therefore cannot execute further commands. Second, you need to define mybuffer as a global variable so that it passes out of the on_message callback. This feels a little clunky but (as far as I know) it is the best way to do what you are trying to do.

The solution to the first problem is simply to use loop_start() instead of loop_forever(). My suspicion is that when you tried this before you didn't put a delay in to give the script time to receive messages. The second problem can be solved simply by adding the line global mybuffer in the on_message callback. This tells python that this is a global variable, not a local one.

Here is some working code that illustrates this:

import paho.mqtt.client as paho
import time

mybuffer = ''

def on_subscribe(client, userdata, mid, granted_qos):
    print('Subscribed')

def on_message(client, userdata, msg):
    global mybuffer
    mybuffer = str(msg.payload)
    print('on_message: '+ mybuffer)

client = paho.Client()
client.on_subscribe = on_subscribe
client.on_message = on_message
client.connect('test.mosquitto.org')
client.subscribe('$SYS/#')

client.loop_start()
time.sleep(1)
client.loop_stop()
print(mybuffer)

However, this is not the best way to accomplish what you are trying to do because it cannot handle multiple messages in a predictable way. A better approach is to wrap all of the code into the on_message call back like this:

import paho.mqtt.client as paho
import time


def on_subscribe(client, userdata, mid, granted_qos):
    print('Subscribed')

def on_message(client, userdata, msg):
    mybuffer = str(msg.payload)
    print('on_message: '+ mybuffer)
    print(mybuffer)

client = paho.Client()
client.on_subscribe = on_subscribe
client.on_message = on_message
client.connect('test.mosquitto.org')
client.subscribe('$SYS/#')

client.loop_forever()

This is a far more robust solution to the problem and, from my perspective, is easier to understand.

Upvotes: 1

Related Questions