stlehmann / Flask-MQTT

Flask Extension for the MQTT protocol
MIT License
207 stars 71 forks source link

Flask-MQTT

Flask Extension for the MQTT protocol. Basically it is a thin wrapper around paho-mqtt and aims to simplify MQTT integration in Flask. MQTT is a machine-to-machine "Internet of Things" protocol and was designed for extremely lightweight publish/subscribe messaging transport.

Inactively Maintained Documentation Status PyPI version CI Coverage Status Downloads Downloads

Find the documentation on http://flask-mqtt.readthedocs.io.

Features

Limitations

Flask-MQTT was developed to provide an easy-to-setup solution for interacting with IoT devices. A typical scenario would be a Raspberry Pi running a mosquitto mqtt server combined with a Flask webserver.

Multiple workers

Flask-MQTT is currently not suitable for the use with multiple worker instances. So if you use a WSGI server like gevent or gunicorn make sure you only have one worker instance.

Reloader

Make sure to disable Flasks autoreloader. If activated it spawns two instances of a Flask application. This leads to the same problems as multiple workers. To prevent Flask-MQTT from running code twice it is necessary to deactivate the automatic reloader.

Installation

Simply install the package as usual via pip:

$ pip install flask-mqtt

Or with conda from the conda-forge channel:

$ conda config --add channels conda-forge
$ conda install flask-mqtt

Usage

Basic Setup

from flask import Flask
from flask_mqtt import Mqtt

app = Flask(__name__)
app.config['MQTT_BROKER_URL'] = 'mybroker.com'
app.config['MQTT_BROKER_PORT'] = 1883
app.config['MQTT_USERNAME'] = 'user'
app.config['MQTT_PASSWORD'] = 'secret'
app.config['MQTT_REFRESH_TIME'] = 1.0  # refresh time in seconds
mqtt = Mqtt(app)

@app.route('/')
def index():
    return render_template('index.html')

Subscribe to a topic

To subscribe to a topic simply use mqtt.subscribe(). To make sure the subscription gets handled correctly on startup place the subscription inside an on_connect() callback function.

@mqtt.on_connect()
def handle_connect(client, userdata, flags, rc):
    mqtt.subscribe('home/mytopic')

To handle the subscribed messages you can define a handling function by decorating it with @mqtt.on_message().

@mqtt.on_message()
def handle_mqtt_message(client, userdata, message):
    data = dict(
        topic=message.topic,
        payload=message.payload.decode()
    )

To unsubscribe do:

mqtt.unsubscribe('home/mytopic')

Or if you want to unsubscribe all topics use unsubscribe_all().

mqtt.unsubscribe_all()

Publish

To publish a message you can use the publish() method.

mqtt.publish('home/mytopic', 'this is my message')

Connect to multiple MQTT Servers

To connect to multiple servers, you can create multiple mqtt clients in your application by specifying the config_prefix when initializing Mqtt()

# default mqtt client
app.config["MQTT_broker_url"] = "example.com"
app.config["MQTT_broker_port"] = 8883
mqtt = Mqtt(app)

# create second mqtt client for a different broker 
app.config["MQTT2_broker_url"] = "example2.com"
app.config["MQTT_broker_port"] = 1883
mqtt2 = Mqtt(app, config_prefix="MQTT2")

# create third mqtt client for a different broker 
app.config["MQTT3_broker_url"] = "example3.com"
app.config["MQTT3_broker_port"] = 1885
mqtt3 = Mqtt(app, config_prefix="MQTT3")

Small publish/subscribe MQTT client

"""

A small Test application to show how to use Flask-MQTT.

"""

import eventlet
import json
from flask import Flask, render_template
from flask_mqtt import Mqtt
from flask_socketio import SocketIO
from flask_bootstrap import Bootstrap

eventlet.monkey_patch()

app = Flask(__name__)
app.config['SECRET'] = 'my secret key'
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.config['MQTT_BROKER_URL'] = 'broker.hivemq.com'
app.config['MQTT_BROKER_PORT'] = 1883
app.config['MQTT_USERNAME'] = ''
app.config['MQTT_PASSWORD'] = ''
app.config['MQTT_KEEPALIVE'] = 5
app.config['MQTT_TLS_ENABLED'] = False
app.config['MQTT_CLEAN_SESSION'] = True

# Parameters for SSL enabled
# app.config['MQTT_BROKER_PORT'] = 8883
# app.config['MQTT_TLS_ENABLED'] = True
# app.config['MQTT_TLS_INSECURE'] = True
# app.config['MQTT_TLS_CA_CERTS'] = 'ca.crt'

mqtt = Mqtt(app)
socketio = SocketIO(app)
bootstrap = Bootstrap(app)

@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('publish')
def handle_publish(json_str):
    data = json.loads(json_str)
    mqtt.publish(data['topic'], data['message'])

@socketio.on('subscribe')
def handle_subscribe(json_str):
    data = json.loads(json_str)
    mqtt.subscribe(data['topic'])

@socketio.on('unsubscribe_all')
def handle_unsubscribe_all():
    mqtt.unsubscribe_all()

@mqtt.on_message()
def handle_mqtt_message(client, userdata, message):
    data = dict(
        topic=message.topic,
        payload=message.payload.decode()
    )
    socketio.emit('mqtt_message', data=data)

@mqtt.on_log()
def handle_logging(client, userdata, level, buf):
    print(level, buf)

if __name__ == '__main__':
    # important: Do not use reloader because this will create two Flask instances.
    # Flask-MQTT only supports running with one instance
    socketio.run(app, host='0.0.0.0', port=5000, use_reloader=False, debug=False)