Hello,
I have run into a very weird problem. And I don’t have any clue why the application is behaving that weirdly. So I’m building an live updating dashboard using dash. The data is received is from an open endpoint https://api.misoenergy.org/MISORTWDDataBroker/DataBrokerServices.asmx?messageType=getace&returnType=json in the json format.
I have created two files one file old_data.json which stores the latest data received from the above url endpoint. The other file old_data_copy.json stores all the data point received plus the new data points. Both the files are stored in a folder named “data/” in the project directory. I basically used a callback function which hit the url every 2 seconds and if there is new data generated then i iterate over them and append them in the old_data_copy.json. In short old_data.json has most recent data from the url, and old_data_copy.json has all the data from the second we started the application.
The problem is that if i open the application in multiple browser windows, it only refreshes one instance, sometimes it doesn’t even refresh at all. I’m not even receiving any errors as well I tried waitress serve using
serve(application, host="127.0.0.1", port=8050, threads=6)
still no help. I also tried Flask to run the application using application.debug = True application.run(threaded=False, processes=3)
I don’t know what is the issue.
Here is the directory structure:
application-
assets/
custom.css
mysoaceup.wav
mysoacedown.wav
data/
old_data.json
old_data_copy.json
resources/
charts.py
get_data.py
application.py
get_data.py → gets the data
charts.py —> return a figure object
application.py
from datetime import timedelta
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
from dash_html_components.Template import Template
import plotly
import plotly.graph_objs as go
from collections import deque
import dash_auth
from dash.dependencies import Input, Output, State
from dash_bootstrap_components._components.Row import Row
from dash_core_components.Loading import Loading
import dash_html_components as html
from dash_html_components.Col import Col
from dash_html_components.Div import Div
from dash_html_components.Hr import Hr
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from requests.api import get
from resources import get_data
from resources import charts
import base64
from flask import Flask
from waitress import serve
import pandas as pd
import json
import config
mysoaceup_sound_filename = "assets/mysoaceup.wav"
mysoaceup_encoded_sound = base64.b64encode(open(mysoaceup_sound_filename, "rb").read())
mysoacedown_sound_filename = "assets/mysoacedown.wav"
mysoacedown_encoded_sound = base64.b64encode(
open(mysoacedown_sound_filename, "rb").read()
)
VALID_USERNAME_PASSWORD_PAIRS = {config.appusername: config.apppassword}
def serve_layout():
# getting initial data from the old_data_copy()
data, msg = get_data.filter_data()
df = get_data.data_to_dataframe(data)
# data = get_data.get_initial_data()
# df = get_data.data_to_dataframe(data)
# print(df.info())
# getting averages
fhr = get_data.get_fhraverage(df)
twlv = get_data.get_12fhraverage(df)
twntyfhr = get_data.get_24fhraverage(df)
frtyeght = get_data.get_48hraverage(df)
initial_trace = go.Scatter(
x=df["instantEST"],
y=df["value"],
name="Scatter",
mode="lines",
line=dict(color="red", width=2),
)
scale_list = [4, 12, 24, 48]
scale_dropdown = dcc.Dropdown(
id="scale_selector",
options=[{"label": i, "value": i} for i in scale_list],
value="4",
optionHeight=25,
multi=False,
clearable=True,
persistence_type="session",
placeholder="Hrs",
)
graph_card = dbc.Card(
dcc.Graph(
id="graph1",
animate=True,
# figure=fig,
figure={
"data": [initial_trace],
"layout": go.Layout(
template="plotly_dark",
xaxis=dict(
range=[
min(df["instantEST"].tolist()),
max(df["instantEST"].tolist()),
],
tickfont=dict(size=8),
),
yaxis=dict(range=[-1000, 1000], tickfont=dict(size=8)),
margin=dict(l=0, r=1, t=0, b=0),
annotations=[
go.layout.Annotation(
text="4hrAvg:{} 12hrAvg:{} 24hrAvg:{} 48hrAvg:{}".format(
fhr, twlv, twntyfhr, frtyeght
),
align="left",
showarrow=False,
xref="paper",
yref="paper",
x=0.5,
y=0,
bordercolor="black",
borderwidth=1,
)
],
),
},
config={"displayModeBar": False},
style={"height": "97.2vh"},
),
body=False,
color="dark",
outline=False,
)
threshold_value = dcc.Input(
id="threshold_value",
type="text",
placeholder="Enter Threshold Values",
debounce=True,
)
app_layout = dbc.Container(
[
html.Div(
[
dbc.Row(
[
dbc.Col(scale_dropdown, width="auto"),
dbc.Col(threshold_value, width="auto"),
],
),
dbc.Row(
dbc.Col(
html.Div(id="threshold-audio", style={"display": "none"})
),
),
dbc.Row(dbc.Col(graph_card)),
dcc.Interval(id="graph-update", interval=2 * 1000),
# html.Audio(id="mysoaceup", src="/assests/mysoaceup.mp3"),
# html.Audio(id="mysoacedown", src="/assests/mysoacedown.mp3"),
dcc.Interval(id="audio-update", interval=2 * 1000),
]
)
],
fluid=True,
)
return app_layout
application = Flask(__name__)
app = dash.Dash(
__name__,
server=application,
suppress_callback_exceptions=True,
external_stylesheets=[dbc.themes.DARKLY],
update_title=None,
)
app.layout = serve_layout
@app.callback(
[Output("graph1", "figure"), Output("threshold-audio", "children")],
[
Input("graph-update", "n_intervals"),
Input("scale_selector", "value"),
Input("threshold_value", "value"),
],
)
def update_graph_scatter(n, value, threshold_value):
data, msg = get_data.filter_data() #returns the old_data_copy.json file
data = get_data.data_to_dataframe(data) # converts the json to dataframe
print(value)
value = int(value)
# if threshold_value is not None:
# upper_value, lwer_value = threshold_value.split(",")
# print(int(upper_value), int(lwer_value))
# else:
# print("No threshold value enters")
# filtering of the data based on selected input
most_recent_timestamp = data["instantEST"].iloc[-1]
# getting averages
fhr = get_data.get_fhraverage(data)
twlv = get_data.get_12fhraverage(data)
twntyfhr = get_data.get_24fhraverage(data)
frtyeght = get_data.get_48hraverage(data)
if value == 4:
fhrsbeforetimestamp = most_recent_timestamp - timedelta(hours=4)
# print(fhrsbeforetimestamp, most_recent_timestamp)
# print(fhrsbeforetimestamp in data["instantEST"].unique())
if fhrsbeforetimestamp in data["instantEST"].unique():
print("from 4")
# print(data[data["instantEST"] == fhrsbeforetimestamp])
location = data[data["instantEST"] == fhrsbeforetimestamp].index[0]
# print(location)
filter_data = data[location:]
# print(filter_data["value"].mean())
fig, msg = charts.plot_4hr_charts(
filter_data, msg, fhr, twlv, twntyfhr, frtyeght
)
if msg == "new_data":
sound_element = audio_update(msg, threshold_value)
return fig, sound_element
else:
return fig, dash.no_update
else:
print("data not available")
fig, msg = charts.plot_4hr_charts(data, msg, fhr, twlv, twntyfhr, frtyeght)
print(msg)
if msg == "new_data":
sound_element = audio_update(msg, threshold_value)
return fig, sound_element
else:
return fig, dash.no_update
# filtering of the data for 12 hr
elif value == 12:
twelvehoursbeforetimestamp = most_recent_timestamp - timedelta(hours=12)
print(twelvehoursbeforetimestamp)
if twelvehoursbeforetimestamp in data["instantEST"].unique():
print("from 12")
location = data[data["instantEST"] == twelvehoursbeforetimestamp].index[0]
filter_data = data[location:]
print(filter_data)
# data = data.tail(1440)
fig, msg = charts.plot_4hr_charts(
filter_data, msg, fhr, twlv, twntyfhr, frtyeght
)
if msg == "new_data":
sound_element = audio_update(msg, threshold_value)
return fig, sound_element
else:
return fig, dash.no_update
else:
print("data not available")
fig, msg = charts.plot_4hr_charts(data, msg, fhr, twlv, twntyfhr, frtyeght)
print(msg)
if msg == "new_data":
sound_element = audio_update(msg, threshold_value)
return fig, sound_element
else:
return fig, dash.no_update
elif value == 24:
twntyfrhoursbeforetimestamp = most_recent_timestamp - timedelta(hours=24)
print(twntyfrhoursbeforetimestamp)
if twntyfrhoursbeforetimestamp in data["instantEST"].unique():
print("from 24")
location = data[data["instantEST"] == twntyfrhoursbeforetimestamp].index[0]
filter_data = data[location:]
fig, msg = charts.plot_4hr_charts(
filter_data, msg, fhr, twlv, twntyfhr, frtyeght
)
if msg == "new_data":
sound_element = audio_update(msg, threshold_value)
return fig, sound_element
else:
return fig, dash.no_update
else:
print("data not avaiable")
fig, msg = charts.plot_4hr_charts(data, msg, fhr, twlv, twntyfhr, frtyeght)
print(msg)
if msg == "new_data":
sound_element = audio_update(msg, threshold_value)
return fig, sound_element
else:
return fig, dash.no_update
else:
fortyeightbeforetimestamp = most_recent_timestamp - timedelta(hours=48)
print(fortyeightbeforetimestamp)
if fortyeightbeforetimestamp in data["instantEST"].unique():
print("from 48")
location = data[data["instantEST"] == fortyeightbeforetimestamp].index[0]
filter_data = data[location:]
fig, msg = charts.plot_4hr_charts(
filter_data, msg, fhr, twlv, twntyfhr, frtyeght
)
if msg == "new_data":
sound_element = audio_update(msg, threshold_value)
return fig, sound_element
else:
return fig, dash.no_update
else:
print("data not avaiable")
fig, msg = charts.plot_4hr_charts(data, msg, fhr, twlv, twntyfhr, frtyeght)
print(msg)
if msg == "new_data":
sound_element = audio_update(msg, threshold_value)
return fig, sound_element
else:
return fig, dash.no_update
# getting today's date
def audio_update(msg, threshold_value):
# data, msg = get_data.filter_data()
# print(msg)
if threshold_value is not None:
upper_value, lwer_value = threshold_value.split(",")
if msg == "new_data":
f = open(
"data/old_data_copy.json",
)
old_data_copy = json.load(f)
f.close()
old_data_copy_df = get_data.data_to_dataframe(old_data_copy)
value1 = old_data_copy_df["value"].iloc[-1]
if value1 > int(upper_value):
return html.Audio(
src="data:audio/mpeg;base64,{}".format(
mysoaceup_encoded_sound.decode()
),
controls=False,
autoPlay=True,
)
if value1 < int(lwer_value):
return html.Audio(
src="data:audio/mpeg;base64,{}".format(
mysoacedown_encoded_sound.decode()
),
controls=False,
autoPlay=True,
)
else:
if msg == "new_data":
f = open(
"data/old_data.json",
)
old_data = json.load(f)
f.close()
f = open(
"data/old_data_copy.json",
)
old_data_copy = json.load(f)
f.close()
old_data_df = get_data.data_to_dataframe(old_data)
old_data_copy_df = get_data.data_to_dataframe(old_data_copy)
value1 = old_data_df["value"].iloc[-1]
value2 = old_data_copy_df["value"].iloc[-5]
if value1 > value2:
return html.Audio(
src="data:audio/mpeg;base64,{}".format(
mysoaceup_encoded_sound.decode()
),
controls=False,
autoPlay=True,
)
if value1 < value2:
return html.Audio(
src="data:audio/mpeg;base64,{}".format(
mysoacedown_encoded_sound.decode()
),
controls=False,
autoPlay=True,
)
if __name__ == "__main__":
serve(application, host="127.0.0.1", port=8050, threads=6)
# app.run_server(debug=True, port=8050, threaded=True, processes=4)
# application.debug = True
# application.run(threaded=False, processes=3)
dash version dash==1.20.0
Let me know how to do this, i don’t have any clue about this. Any help would be appreciated. I want all my users to get updated as fast as possible thankyou.
If you need any additional info let me know.