Python Flask Server MQTT can't interact with socket.io

Viewed 393
Server:
Ubuntu 18.04.3 LTS
python3.6

I want show device's message on web, my structure like:

Device--(MQTT)-->Server--(socket.io)-->Web

First, I publish message by mqtt to Server, and Server successed subscribed to get message .

Second, I use socket.io to send message to Web, but problem is here, if Server send message by socket.io after mqtt.on_message, the web's socket.io will be stuck, until refresh web.

My Flask Server a part of code:

from flask import Flask, request, render_template, flash, redirect, url_for
from flask_mqtt import Mqtt
from flask_socketio import SocketIO
from flask_bootstrap import Bootstrap
from flask_login import UserMixin, LoginManager, login_required, current_user, login_user, login_required, logout_user
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from forms import RegisterForm, LoginForm, AddForm, ChangePasswordForm
import pymysql
from config import Config
from sqlalchemy.ext.declarative import declarative_base
import json
import plotly as py
from datetime import datetime
import eventlet
eventlet.monkey_patch()
# MQTT
app = Flask(__name__)
bcrypt = Bcrypt(app)
app.config['SECRET'] = ''
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.config['MQTT_BROKER_URL'] = ''
app.config['MQTT_BROKER_PORT'] = 
app.config['MQTT_USERNAME'] = ''
app.config['MQTT_PASSWORD'] = ''
app.config['MQTT_KEEPALIVE'] = 5
app.config['MQTT_TLS_ENABLED'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = ''
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
mqtt = Mqtt(app)
socketio = SocketIO(app, cors_allowed_origins='*')

if __name__ == '__main__':
    socketio.run(app, keyfile='privkey.pem', certfile='fullchain.pem', host='0.0.0.0', port=5002, use_reloader=True, debug=True)

Flask Server MQTT and socket.io part of code:

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

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

    if(topic[0] == "test"):
        socketio.emit('web', "received")

Web Client javascript code:

    socket.on('web', function(data) {
      console.log(data);
    })

If just use socket.io to send message to web didn't use mqtt it's work fine. I don't know why they can't interact together. Then I find something on flask-mqtt offical file about "MQTT Interact with SocketIO", example code the difference from me is "import eventlet". So i guess is abotu threading problem? But when i also import it will show error, the error is:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/eventlet/hubs/hub.py", line 461, in fire_timers
    timer()
  File "/usr/local/lib/python3.6/dist-packages/eventlet/hubs/timer.py", line 59, in __call__
    cb(*args, **kw)
  File "/usr/local/lib/python3.6/dist-packages/eventlet/greenthread.py", line 221, in main
    result = function(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/eventlet/wsgi.py", line 818, in process_request
    proto.__init__(conn_state, self)
  File "/usr/local/lib/python3.6/dist-packages/eventlet/wsgi.py", line 357, in __init__
    self.handle()
  File "/usr/local/lib/python3.6/dist-packages/eventlet/wsgi.py", line 390, in handle
    self.handle_one_request()
  File "/usr/local/lib/python3.6/dist-packages/eventlet/wsgi.py", line 419, in handle_one_request
    self.raw_requestline = self._read_request_line()
  File "/usr/local/lib/python3.6/dist-packages/eventlet/wsgi.py", line 402, in _read_request_line
    return self.rfile.readline(self.server.url_length_limit)
  File "/usr/lib/python3.6/socket.py", line 586, in readinto
    return self._sock.recv_into(b)
  File "/usr/local/lib/python3.6/dist-packages/eventlet/green/ssl.py", line 241, in recv_into
    return self._base_recv(nbytes, flags, into=True, buffer_=buffer)
  File "/usr/local/lib/python3.6/dist-packages/eventlet/green/ssl.py", line 256, in _base_recv
    read = self.read(nbytes, buffer_)
  File "/usr/local/lib/python3.6/dist-packages/eventlet/green/ssl.py", line 176, in read
    super(GreenSSLSocket, self).read, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/eventlet/green/ssl.py", line 146, in _call_trampolining
    return func(*a, **kw)
  File "/usr/lib/python3.6/ssl.py", line 874, in read
    return self._sslobj.read(len, buffer)
  File "/usr/lib/python3.6/ssl.py", line 631, in read
    v = self._sslobj.read(len, buffer)
ssl.SSLWantReadError: The operation did not complete (read) (_ssl.c:2309)

I searched about this error, some result say this is eventlet's Bug on python3, Is any solution for this error?

0 Answers
Related