Use Dash with websockets
Asked Answered
D

3

7

What is the best way to use Dash with Websockets to build a real-time dashboard ? I would like to update a graph everytime a message is received but the only thing I've found is calling the callback every x seconds like the example below.

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_daq as daq
from dash.dependencies import Input, Output
import plotly
import plotly.graph_objs as go
from websocket import create_connection
from tinydb import TinyDB, Query
import json
import ssl


# Setting up the websocket and the necessary web handles
ws = create_connection(address, sslopt={"cert_reqs": ssl.CERT_NONE})


app = dash.Dash(__name__)
app.layout = html.Div(
    [
        dcc.Graph(id='live-graph', animate=True),
        dcc.Interval(
            id='graph-update',
            interval=1*1000,
            n_intervals=0)
    ]
)

@app.callback(Output('live-graph', 'figure'),
              [Input('graph-update', 'n_intervals')])

def update_graph_live(n):

    message = ws.recv()
    x=message.get('data1')
    y=message.get('data2')
        .....


    fig = go.Figure(
        data = [go.Bar(x=x,y=y)],
        layout=go.Layout(
            title=go.layout.Title(text="Bar Chart")
            )
        )
    )

    return fig

if __name__ == '__main__':
    app.run_server(debug=True)

Is there a way to trigger the callback everytime a message is received (maybe storing them in a database before) ?

Derive answered 9/9, 2019 at 19:37 Comment(0)
J
2

You could have a look at the Websocket component from the Dash Extensions package. As you can see at the example, the package provides a WebSocket component that is included in your app's layout. Messages can be received in callbacks by the message property of WebSocket.

Regarding this, the solution to your problem would be like:

from dash_extensions import WebSocket
from dash_extensions.enrich import callback, dcc, html, Input, Output, DashProxy
# all dash imports are replaced by dash_extensions
import plotly.graph_objs as go

app = DashProxy(__name__)
app.layout = html.Div(
    [
        dcc.Graph(id='live-graph', animate=True),
        WebSocket(id='ws', url="ws:...")  # Websocket address is inserted here
    ]
)

@callback(Output('live-graph', 'figure'),
          Input('ws', 'message'))
def update_graph_live(msg):
    # Parsing msg depends on its structure, e.g.:
    x = msg['x']
    y = msg['y']

    fig = go.Figure(
        data=[go.Bar(x=x,y=y)],
        layout=go.Layout(
            title=go.layout.Title(text="Bar Chart")
        )
    )
    return fig

The link above delivers further details about this topic, e.g. about the websocket setup.

Joyajoyan answered 27/4, 2023 at 13:33 Comment(0)
M
0

This forum post describes a method to use websocket callbacks with Dash:

https://community.plot.ly/t/triggering-callback-from-within-python/23321/6

Update

Tried it, it works well. Environment is Windows 10 x64 + Python 3.7.

To test, download the .tar.gz file and run python usage.py. It will complain about some missing packages, install these. Might have to edit the address from 0.0.0.0 to 127.0.0.1 in usage.py. Browse to http://127.0.0.1:5000 to see the results. If I had more time, I'd put this example up on GitHub (ping me if you're having trouble getting it to work, or the original gets lost).

Mesopause answered 18/1, 2020 at 8:52 Comment(4)
Hey contango, I chanced upon your answer and would like to ask a little more about it. Do you mind if we chat for a bit?Formicary
@Formicary Sure. I did get it to work but never used it in the end. It will publish the same information out to every connected client. What do you use for chat?Mesopause
Hey contango thank you for your reply. However, I managed to get it to work so there is no need to trouble you. Thanks for offering to help! :)Formicary
@Formicary Great! Glad you have a solution. If you can post any extra information as another answer for the latest version of Dash it would help to pay it forward :) Even the versions of Dash you used would be helpful.Mesopause
F
-1

I had two separate servers: one for dash, the other one as a socket server. They are running on different ports. On receiving a message, I edited a common json file to share information to dash's callback. That's how I did it.

Formicary answered 29/5, 2020 at 4:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.