2

I am setting up a dashboard which requires a Python Flask server to fetch public transport data once every few seconds or so and send this data to a client webpage through websockets. I am using FlaskSocketIO to achieve this.

I am able to send a message upon the 'connect' event, for example, but I've been unable to find a way to continuously update this message. This is my approach:

from flask import Flask, render_template, url_for, request
from flask_socketio import SocketIO, emit, send
import eventlet
eventlet.monkey_patch()

app = Flask(__name__)
socketio = SocketIO(app, logger=True, engineio_logger=True)

def listen():
    while True:
        message = # some updating message
        emit('message', message)
        socketio.sleep(1)

@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('connect')
def handle_connect():
    listen()

if __name__ == "__main__":
    socketio.run(app, debug=True)

The logger says it sends the message. However, on the client side, no message is recieved. The client side JavaScript is:

var socket = io();

socket.on('message', function(msg) {
    console.log(msg);
});

2 Answers 2

2

i have the same problem with you, in my case i wanted to update sensor dashboard, so i study about Observer Pattern, this link is really good Observer Pattern.Implement a SocketEmitObservator, using the Observer you dont need to create a listener(infinite while loop) and make your code more clean:

class SensorObserver(Observer):
    sensor_id: int
    sid = ''

    def __init__(self, sid,sensor_id=None):
        Observer.__init__(self)
        self.sensor_id = sensor_id
        self.sid = sid
        SensorPublisher().attach(self)

    def update(self, sensorData: DataModel) -> None:
        socket.emit("info",
                        {'sensor': subject},
                        namespace='/api/sector/machine',
                        room=self.sid)

    def __del__(self):
        SensorPublisher().detach(self)

class SensorPublisher(Subject, Singleton):
    _observers: List[SensorObserver] = []
    _sensorData: Dict[str, DataModel] = {}

    def attach(self, observer: SensorObserver) -> None:
        if observer not in self._observers:
            self._observers.append(observer)

    def notify(self, sensorModel: DataModel) -> None:
        for observer in self._observers:
            if sensorModel.sensor_id == observer.sensor_id:
                observer.update(sensorModel)

    def detach(self, observer: SensorObserver) -> None:
        if observer in self._observers:
            ob = self._observers.pop(self._observers.index(observer))
            del ob

    def update(self, sensorModel: DataModel):
        sendorId: str = str(sensorModel.sensor_id)
        self._sensorData[sendorId] = sensorModel
        self.notify(sensorModel)


#### And in the place where i update sensor data i put
SensorPublisher().update(dataStructList)

#### To create a observr just do
@socketio.on('connect')
def handle_connect():
    SensorObserver(self.sid, item)

In my case i use like this, but you can adapt for your problem

Sign up to request clarification or add additional context in comments.

Comments

1

You cannot add a while True loop in the connect handler, as that will prevent the connect handler from returning and establishing the connection.

You can do this as a response to another event sent by the client after the connection is made, or you can also start a background task that implements this loop. The connect handler needs to return quickly to allow the connection to happen.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.