Question

I am a TOTAL newbie to python and have very basic MQTT knowledge.

I am trying to write a python script that subscribes to a wildcard topic and then builds a list of the topics under the wildcard. I understand that the MQTT protocol does not cater for this, so I need to accomplish this via python. I was thinking about placing the topic and message in an array.

I have the following topics:

/weather/current/temperature

/weather/current/humidity

/weather/current/pressure

/weather/current/time

In my python script I am subscribing to /weather/current/#.

For example, I imagine the array would be something like this:

[/weather/current/temperature,message]

[/weather/current/humidity,message]

[/weather/current/pressure,message]

[/weather/current/time,message]

My script is pretty much the standard example in which I have tried several methods to achieve this but fail. I think my root issue is my lack of understanding regarding the on_message function. Is it executed once for all the topics or once per topic ?

def on_connect(mqttc, obj, rc):
    print("rc: "+str(rc))

def on_message(mqttc, obj, msg,):
    # print(msg.topic+" "+str(msg.payload))
    payload = str(msg.payload)
    print(msg.topic+" Payload -> "+payload)

def on_publish(mqttc, obj, mid):
    print("mid: "+str(mid))

def on_subscribe(mqttc, obj, mid, granted_qos):
    print("Subscribed: "+str(mid)+" "+str(granted_qos))

def on_log(mqttc, obj, level, string):
    print(string)

try:
    mqttc = mqtt.Client("Python-MQTT-Sub")

    mqttc = mqtt.Client()
    mqttc.on_message = on_message
    mqttc.on_connect = on_connect
    mqttc.on_publish = on_publish
    mqttc.on_subscribe = on_subscribe
    # Uncomment to enable debug messages
    #mqttc.on_log = on_log
    mqttc.connect("localhost", 1883, 60)
    mqttc.subscribe("/weather/current/#", 0)

    mqttc.loop_forever()

except KeyboardInterrupt:
    print("\ninterrupt received, exiting...")
Was it helpful?

Solution

As @ralight said above, on_message is called on receipt of a message (which may or may not be a retained message). To illustrate, I've changed your code very slightly to add an array called topic_names which is populated as messages arrive at the program.

import paho.mqtt.client as mqtt 

topic_names = []

def on_message(mqttc, obj, msg,):
    # print(msg.topic + " " + str(msg.payload))
    payload = str(msg.payload)
    print(msg.topic + " Payload -> " + payload)

    topic_names.append(msg.topic)

try:
    mqttc = mqtt.Client()
    mqttc.on_message = on_message

    mqttc.connect("localhost", 1883, 60)
    mqttc.subscribe("weather/current/#", 0)

    mqttc.loop_forever()

except KeyboardInterrupt:
    print "Received topics:"
    for topic in topic_names:
        print topic

Running this program and publishing two messages to it shows

weather/current/temp Payload -> Fair
weather/current/humidity Payload -> 10
^C
weather/current/temp
weather/current/humidity

OTHER TIPS

on_message will get called on receipt of a message from the broker. This could be a message for any topic that you are subscribed to, so anything /weather/current and up. Messages are all distinct events even though you only used a single subscription.

Another minor point - it's not usually a good idea to hard code the client id unless you are using clean session set to false. Duplicate client ids result in you being disconnected from the broker. Either generate something that is unique on your own, or leave client_id missing in the call to Client() which will then use the default value of None which means the client id is generated randomly for you.

A final thing - there is no real need to start topics with a leading slash unless you have other reasons to do so. The leading slash actually adds an extra level of hierarchy with the first level being an empty string. It's not exactly what you might expect so can be confusing in some situations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top