-1

all!

I am developing an application which receives data from a temperature sensor and prints it dynamically in a flask-served webpage at localhost:5000.

To receive the data from the temperature sensor, an udp server is employed. The receive function is implemented inside a thread. To "real-time" print data to the webpage, socketio is employed - it all runs inside "app.py".

The problem which I am facing is the slowness to print data in the webpage. To test my code I developed an udp client (client.py) which connects to my app.py and, via user input, sends data. What I am observing is that the socket receives the data (I am able to print everything I send in client.py and everything I receive in app.py) but something between my socketio emit function and the website feedback makes this update process slow.

Am I missing something? Could you guys help me out discovering why is this process so slow in my code?

All help is much appreciated!! Many thanks!!

app.py

from flask import Flask, render_template, flash, url_for, redirect, request
from flask_sqlalchemy import SQLAlchemy
from flask_socketio import SocketIO, emit
import socket
import threading

HOST = ''
PORT = 3456
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
orig = (HOST, PORT)
udp.bind(orig)

app = Flask(__name__)
app.config ['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///measurements.sqlite3'
app.config ['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = "secret!"

async_mode = None
socketio = SocketIO(app, async_mode=async_mode)

def thread_function():
    last_temp = 0

    while True:
        temperatura, client = udp.recvfrom(5)
        temp = float(temperatura)
        print("Temp: " + str(temp))
        print("Last temp: " + str(last_temp))

        if (temp != last_temp):
            socketio.emit('my_response', {'temp': temp})
            print("I am here!")
            last_temp = temp

    udp.close()


receive_thread = threading.Thread(target=thread_function)
receive_thread.start()

@app.route('/')
def home():
    # Home acts as a dashboard for the page
    return render_template('index.html')

if __name__ == '__main__':
    socketio.run(app)

client.py

import socket

HOST = '127.0.0.1'  
PORT = 3456            
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
dest = (HOST, PORT)

print('Para sair use CTRL+X\n')

msg = input()

while msg != '\n':
    udp.sendto(bytes(msg, "utf-8"), dest)
    msg = input()

udp.close()

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Temperature sense</title>
    <style>
    img {
      display: block;
      margin-left: auto;
      margin-right: auto;
    }
    button {
      background-color: #4180a0;
      border: none;
      border-radius: 8px;
      color: white;
      <!--- padding: 32px 64px; --->
      text-align: center;
      text-decoration: none;
      display: inline-block;
      font-size: 16px;
      <!--- margin: 4px 2px; --->
      cursor: pointer;
      width: 128px;
      height: 64px;
    }
    button.button:hover{
        background-color: #2a2349;
    }
    div {
        border: 1px;
        border-style: solid;
        border-color: #bebbb2;
        padding: 8px;
    }
    measurementPrint{
        border: 1px;
        border-style: solid;
        border-color: #bebbb2;
        padding: 8px;
    }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js" integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ==" crossorigin="anonymous"></script>
    <script type="text/javascript" charset="utf-8">
        $(document).ready(function() {
            // Connect to the Socket.IO server.
            // The connection URL has the following format, relative to the current page:
            //     http[s]://<domain>:<port>[/<namespace>]
            var socket = io();

            // Event handler for server sent data.
            // The callback function is invoked whenever the server emits data
            // to the client. The data is then displayed in the "Received"
            // section of the page.

            socket.on('my_response', function(msg) {
                $('#log').text(msg.temp);
            });

        });
    </script>
</head>

<body>
    <div>

        <img src="/static/images/mentorphotonics.jpeg" class="center" alt="Mentor Photonics"  width="200" height=auto />

        <p>
            <a href=/ ><button class=button >Realtime</button></a>
                <measurementPrint>
                    <b>Temperature: <span id="log"></span></b>
                </measurementPrint>
        </p>
        <p><a href=export ><button class=button >Export</button></a></p>
        <p><a href=about ><button class=button >About</button></a></p>
    </div>
</body>

</html>

1 Answers1

0

guys

I re-studied the example from Miguel Grinberg's tutorial at https://github.com/miguelgrinberg/Flask-SocketIO and I adjusted the code. The main issues were:

  1. I was not using the "thread = socketio.start_background_task(background_thread)" structed, as he used with the @socketio.event
  2. UDP's recvfrom is blocking. To solve this issue I set a timeout "udp.settimeout(0.1)" so it becomes non-blocking. However, now you should use the try;exception pair when the timeout occurs.

Regards, Fávero