pythonflaskmqttpythonanywhere

Flask app with MQTT client not receiving messages when deployed as web app


I created a simple Python flask app that uses a MQTT client to received messages and then post it to the flask application. The program runs as expected when run on my local machine, but never receives/posts messages when deployed on pythonanywhere.com. I upgraded my account on the site, as connecting to a not whitelisted mqtt broker is now allowed for free users, so that shouldn't be the problem. I use a simple string concat with some name like "clientReceiver" + str(time.time()) to avoid clients having the same name when creating new instances.

I have tried both using the flask_mqtt library as well as the paho.mqtt library, both have the same issue. If i run a separate mqtt client on my local PC that posts to the flask app that is deployed, it receives the messages, but not on its own.

Heres the code for the mqtt client:

info = Info(title='AIR API', version='1.0.0')
app = OpenAPI(__name__, info=info, template_folder='templates')
air_tag = Tag(name='air', description='air data operations')

app.config['MQTT_BROKER_URL'] = "boker.url"
app.config['MQTT_BROKER_PORT'] = 8883
app.config['MQTT_USERNAME'] = "username"
app.config['MQTT_PASSWORD'] = "password"
app.config['MQTT_CLIENT_ID'] = "clientReceive" + str(time.time())
app.config['MQTT_TLS_ENABLED'] = True
app.config['MQTT_TLS_CA_CERTS'] = None
app.config['MQTT_TLS_CERTFILE'] = None
app.config['MQTT_TLS_KEYFILE'] = None
app.config['MQTT_TLS_CERT_REQS'] = ssl.CERT_NONE
app.config['MQTT_TLS_VERSION'] = ssl.PROTOCOL_TLS_CLIENT

topic = "mytopic"

mqtt = Mqtt(app)

@mqtt.on_connect()
def on_connect(client, userdata, flags, rc):
    # Code to execute when the MQTT client connects to the broker
    # This function is called automatically when a connection is established.
    print("Connected with result code " + str(rc))
    client.subscribe(topic)


@mqtt.on_message()
def on_message(client, userdata, message):
    # Code to execute when a message is received on a subscribed topic
    # This function is called automatically when a message is received.
    data = message.payload.decode()
    headers = {'Content-Type': 'application/json'}

    try:
        response = requests.post('mysite/whereipost', data=data,
                                 headers=headers)
        if response.status_code == HTTPStatus.CREATED:
            print('Data received and stored')
            print("Data: " + data)
        else:
            print('Error storing data, status code:', {response.status_code})
    except Exception as e:
        print(f"failed to forward message to Flask endpoint: {e}")

And the code used for the posting on the flask app:

@app.route('/api/core2/sensors/air-quality', methods=['POST'])
def post_air_data(Body: AirData):
    """ Adds a new air data measurement """

    measurements.data.append(Body)

    # Get the time of the last measurement
    times.time.append(dateTime(time=datetime.datetime.now()))

    return AirDataId(id=len(measurements.data) - 1).json(), HTTPStatus.CREATED

Solution

  • Problem statet by Brits in comment on post. flask_mqtt calls the paho.mqtt loop_start() function which uses threads. Threads are not supported on pythonanywhere.com, which effectively makes it so it just ignores the code. To solve this i made a seperate program and ran it as an always-on-task instead.