как запустить mqtt в flask приложении одновременно через wsgi - PullRequest
0 голосов
/ 26 марта 2020

Я создал приложение flask, состоящее из MQTT-клиента, который одновременно подписывает данные из esp32 и сохраняет их в базе данных.


from flask import Flask, redirect, render_template, request, session, abort,make_response,jsonify, flash, url_for
import paho.mqtt.client as mqtt
import json
import config
import db_access

#mqtt code
def on_message(client, userdata, message):
    topic = message.topic
    print("line 12 - topic checkpoint - ",topic)
    msgDecode=str(message.payload.decode("utf-8","ignore"))
    msgJson=json.loads(msgDecode) #decode json data
    print("line 15 - json checkpoint - ",type(msgJson))
    # deviceID = msgJson["DeviceID"]
    # currentCounter = msgJson["Counter"]
    # status = msgJson["Status"]    
   db_access.updateStatus(msgJson["DeviceID"],msgJson["Status"])



app = Flask(__name__,template_folder='templates')



'''Web portal routes'''

@app.route('/device/switch', methods=['POST'])
def switch():
    #parameter parsing
    deviceID = request.args.get('deviceID')
    status = request.args.get('status')
    statusMap = {"on":1,"off":0}

    #MQTT publish
    mqtt_msg = json.dumps({"deviceID":int(deviceID),"status":statusMap[status]})
    client.publish(config.MQTT_STATUS_CHANGE_TOPIC,mqtt_msg)

   time_over_flag = 0
    loop_Counter = 0

    while status != db_access.getDeviceStatus(deviceID):
        time.sleep(2)
        loop_Counter+=1
        if loop_Counter ==2:
            time_over_flag = 1
            break

    if time_over_flag:
        return make_response(jsonify({"statusChange":False}))
    else:
        return make_response(jsonify({"statusChange":True}))


if __name__ == "__main__":
    db_access.createUserTable()
    db_access.insertUserData()
    db_access.createDeviceTable()
    db_access.insertDeviceData()


    print("creating new instance")
    client = mqtt.Client("server") #create new instance
    client.on_message=on_message #attach function to callback
    print("connecting to broker")
    client.connect(config.MQTT_BROKER_ADDRESS)
    client.loop_start()
    print("Subscribing to topic","esp/#")
    client.subscribe("esp/#")
   app.run(debug=True, use_reloader=False)

Это код в ____ init ____. Py

db_access .py состоит из операций базы данных, а config.py состоит из конфигураций. Будет ли это работать в apache? также у меня нет опыта работы с WSGI

1 Ответ

0 голосов
/ 27 марта 2020

Проблема с запуском вашего кода (как входит в комплект) на сервере WSGI заключается в том, что часть этого последнего блока if запускается только при непосредственном выполнении этого файла с помощью команды python.

Чтобы это работало, я бы попробовал переместить этот блок кода в начало вашего файла, вот здесь:

app = Flask(__name__,template_folder='templates')

db_access.createUserTable()
db_access.insertUserData()
db_access.createDeviceTable()
db_access.insertDeviceData()

print("creating new instance")
client = mqtt.Client("server") #create new instance
client.on_message=on_message #attach function to callback
print("connecting to broker")
client.connect(config.MQTT_BROKER_ADDRESS)
client.loop_start()
print("Subscribing to topic","esp/#")
client.subscribe("esp/#")

Я бы также переименовал этот файл __init__.py во что-то вроде server.py поскольку файл инициализации не должен быть тяжелым.

После того, как вы это сделаете, снова запустите его с сервером разработки и проверьте, что он работает должным образом.

Затем установите WSGI-сервер, похожий на gunicorn в вашей виртуальной среде:

pip install gunicorn

И запустите приложение с gunicorn (эта команда должна работать, если вы переименовали свой файл в server.py):

gunicorn --bind '0.0.0.0:5000' server:app

Затем проверьте снова.

...