Issue
I am trying to read serial data on a raspberry pi and display it on a webpage within a Flask server
The issue that I am having is that when I run the code with both threads started, the thread that is listening for serial input is not running and only the flask server thread is running.
When running just the serial read thread, I can read what is being sent.
How can I allow both of these threads to run parallel, to allow the message to be displayed on the webpage?
Thanks
from flask import Flask, render_template, request, url_for, flash, redirect, Response
from flask_socketio import SocketIO, emit
from threading import Thread
import time
import serial
global serialMessage
serialMessage = ""
class SerialReadProgram:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
def run(self):
global serialMessage
ser = serial.Serial ("/dev/ttyS0", 9600)
print("Serial Start")
while self._running:
serialMessage = ser.read() #read serial port
time.sleep(0.03)
data_left = ser.inWaiting() #check for remaining byte
serialMessage += ser.read(data_left)
print (serialMessage)
class FlaskServer:
app = Flask(__name__)
socketio = SocketIO(app=app, cors_allowed_origins='*')
def __init__(self):
self._running = True
def terminate(self):
self._running = False
@app.route('/', methods=('GET', 'POST'))
def home():
if request.method == 'POST':
message = request.form['message']
print(message)
return render_template('index.html')
# Handler for a message recieved over 'connect' channel
@socketio.on('connect')
def test_connect():
emit('after connect', {'data':'Connnected'})
@socketio.on('Fetch For Data')
def value_changed():
global cycle
emit('Updated Message', {'data': serialMessage}, broadcast=True)
socketio.run(app, host='0.0.0.0', allow_unsafe_werkzeug=True)
#Create Class
SerialRead = SerialReadProgram()
#Create Thread
SerialReadThread = Thread(target=SerialRead.run)
#Start Thread
SerialReadThread.start()
#Create Class
Flask = FlaskServer()
#Create Thread
FlaskThread = Thread(target=Flask)
#Start Thread
FlaskThread.start()
Solution
Converting my comment as an answer
socketio.run
creates it's own thread so don't need to run it in thread just run normal socketio server and serial in diffrent thread.
So your code will look like this
from flask import Flask, render_template, request
from flask_socketio import SocketIO, emit
from threading import Thread
import time
import serial
app = Flask(__name__)
socketio = SocketIO(app=app, cors_allowed_origins='*')
serial_message = ""
class SerialReadProgram:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
def run(self):
global serial_message
ser = serial.Serial("/dev/ttyS0", 9600)
print("Serial Start")
while self._running:
serial_message = ser.readline().decode().strip() # read serial port
print(serial_message)
time.sleep(0.03)
@app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
message = request.form['message']
print(message)
return render_template('index.html')
@socketio.on('connect')
def test_connect():
emit('after connect', {'data': 'Connected'})
@socketio.on('Fetch For Data')
def value_changed():
global serial_message
emit('Updated Message', {'data': serial_message}, broadcast=True)
if __name__ == '__main__':
serial_read = SerialReadProgram()
serial_read_thread = Thread(target=serial_read.run)
serial_read_thread.start()
socketio.run(app, host='0.0.0.0', debug=True)
Answered By - Ankit Tiwari Answer Checked By - David Goodson (WPSolving Volunteer)