Search code examples
pythonflaskserveribm-cloudmqtt

Python Flask server with MQTT subscription


I have a flask server written in Python running on IBM BlueMix. I want this server to listen to a MQTT channel and publish a message when it receives a message. I have the following code but on_connect and on_message are never called.

app = Flask(__name__)
def on_connect(client):
    client.publish(topic2, "CONNECTED")


def on_message(client, userdata, msg):
    client.publish(topic2, "MESSAGE")


@app.route('/')
def hello_world():
    return 'Hello World! I am running on port ' + str(port)

if __name__ == '__main__':
    client = mqtt.Client()
    client.username_pw_set(username, password)
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect('broker.example.com')
    client.subscribe(topic)
    client.publish(topic2, "STARTING SERVER")

    app.run(host='0.0.0.0', port=port)

I've tried client.loop and client.loop_forever but it doesn't work.

EDIT: client.publish(topic2, "STARTING SERVER") is working, my credentials are removed.


Solution

  • You need to pass the details of the broker you want to connect to in the connect() function

    e.g.

    ...
    client.on_message = on_message
    client.connect('broker.example.com')
    client.subscribe(topic)
    ...
    

    EDIT: you also need to start the network loop. Given this is flask app you will want to start the loop in the background so use the loop_start function.

    ...
    client.connect('broker.example.com')
    client.loop_start()
    ...
    

    You should also move the subscribe and publish calls to the on_connect callback as they need to wait for the connection to have been established before being run.

    EDIT2: adding full working code:

    from flask import Flask
    import paho.mqtt.client as mqtt
    
    app = Flask(__name__)
    
    topic = 'foo'
    topic2 = 'bar'
    port = 5000
    
    def on_connect(client, userdata, flags, rc):
        client.subscribe(topic)
        client.publish(topic2, "STARTING SERVER")
        client.publish(topic2, "CONNECTED")
    
    
    def on_message(client, userdata, msg):
        client.publish(topic2, "MESSAGE")
    
    
    @app.route('/')
    def hello_world():
        return 'Hello World! I am running on port ' + str(port)
    
    if __name__ == '__main__':
        client = mqtt.Client()
        #client.username_pw_set(username, password)
        client.on_connect = on_connect
        client.on_message = on_message
        client.connect('localhost')
        client.loop_start()
    
        app.run(host='0.0.0.0', port=port)