app.py file:
from flask import Flask
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import operator
from threading import Thread
from opcua import Client
import time
import os
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from opc_functions import save_opc_values
from plot_functions import plot_data
from view_all import view_layout
SERVER_LINK = 'opc.tcp://localhost:4841/freeopcua/server/'
OBJECTS = ['1:metric_value.1', '2:metric_value.2', '3:metric_value.3']
external_stylesheets = ['https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css']
server = Flask(__name__)
app = dash.Dash(__name__, server=server, external_stylesheets=external_stylesheets)
app.config.suppress_callback_exceptions = True
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='test', hidden=True),
html.Div(id='page-content',
children=view_layout)
])
# Change the title of tabs
@server.route("/")
def main_tab_title():
app.title = "Anomaly detection"
return app.index()
@app.callback(Output('graphics_view', 'children'),
[Input('interval_graph_view', 'n_intervals')])
def plot_machines(n_intervals):
start_time = time.time()
print('entered plot_machines')
machines_list = os.listdir('data')
div_children = []
cols = 2
rows = len(machines_list)//cols
rows = rows + 1 if len(machines_list)%cols > 0 or rows == 0 else rows
fig = make_subplots(rows=rows, cols=cols)
ind = 0
for machine in machines_list:
data = pd.read_csv(os.path.join('data', machine))
# fig = go.Figure()
row = ind // cols + 1
col = ind % cols + 1
fig = plot_data(fig, machine, data,
row=row, col=col)
ind += 1
div_children.append(
dcc.Graph(
# id=f"{machine}_graph",
figure=fig,
)
)
print('plotted')
return div_children
@app.callback(Output('machines_list', 'children'),
[Input('Add_machine', 'n_clicks_timestamp'),
Input('Delete_machine', 'n_clicks_timestamp')],
[State('machines_list', 'children')])
def stream_machines(add_clicked, delete_clicked,
# States
machines_list):
print('entered stream_machines')
start_time = time.time()
add_clicked = add_clicked or 0
delete_clicked = delete_clicked or 0
machines_list = machines_list or []
# find last clicked item
clicks_dict = {'add': add_clicked,
'delete': delete_clicked}
clicked = max(clicks_dict.items(), key=operator.itemgetter(1))[0]
if clicks_dict[clicked] != 0:
if clicked == 'add':
machine = f'Machine_{len(machines_list)+1} '
machines_list.append(machine)
client = Client(SERVER_LINK)
client.connect()
root = client.get_root_node()
p1 = Thread(target=save_opc_values,
args=(machine, root, client, OBJECTS),
name=machine)
p1.start()
elif clicked == 'delete' and len(machines_list) > 0:
machine_to_drop = machines_list[-1]
# stop threading
save_opc_values.stop = machine_to_drop
# delete saved files
file_path = os.path.join('data', f'{machine_to_drop}.csv')
if os.path.exists(file_path):
os.remove(file_path)
machines_list = machines_list[:-1]
time.sleep(3)
# print('stream_machines time = ', time.time() - start_time)
return machines_list
if __name__ == '__main__':
app.run_server(port=80, host='0.0.0.0')
plot function:
def plot_data(fig, machine, df, row, col):
# Add legend and title
fig.update_layout(showlegend=True,
title={
'text': machine,
# location of the title in ratio
'y': 0.9,
'x': 0.5
})
x = df.iloc[:, 0]
for column in df.columns[1:]:
fig.add_trace(go.Scatter(x=x,
y=df[column],
name=column
),
row=row, col=col)
return fig
If you’ll need some other functions, I’ll add.
Really need your help!