homecontrol-dash: select range, limits, arrange in columns, cleanup
This commit is contained in:
parent
4b7f2662b8
commit
09412adcfb
2 changed files with 132 additions and 45 deletions
1
Pipfile
1
Pipfile
|
@ -8,6 +8,7 @@ verify_ssl = true
|
|||
[packages]
|
||||
dash = "*"
|
||||
dash-daq = "*"
|
||||
dash-bootstrap-components = "*"
|
||||
requests = "*"
|
||||
|
||||
[requires]
|
||||
|
|
|
@ -1,22 +1,49 @@
|
|||
#!/usr/bin/env python3
|
||||
import dash
|
||||
import dash_bootstrap_components as dbc
|
||||
import dash_core_components as dcc
|
||||
import dash_html_components as html
|
||||
from dash.dependencies import Input, Output
|
||||
import time
|
||||
import requests
|
||||
from math import inf
|
||||
|
||||
URL_BASE="http://innocence:5000"
|
||||
|
||||
x = [1]
|
||||
y = [2]
|
||||
def get_sensors():
|
||||
ret = {}
|
||||
try:
|
||||
url = "%s/sensor/get" % URL_BASE
|
||||
res = requests.get(url)
|
||||
ret = res.json()
|
||||
except Exception as ex:
|
||||
print('Exception Type:%s, args:\n%s' % (type(ex).__name__, ex.args))
|
||||
return ret
|
||||
|
||||
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
|
||||
|
||||
def get_values(sensorId, min_ts, max_ts, limit):
|
||||
ret = {}
|
||||
if sensorId:
|
||||
try:
|
||||
url = "%s/sensor/get_values/%s?min_ts=%s&max_ts=%s&limit=%s" % (URL_BASE,
|
||||
sensorId, min_ts, max_ts, limit)
|
||||
res = requests.get(url)
|
||||
ret = res.json()[sensorId]
|
||||
except Exception as ex:
|
||||
print('Exception Type:%s, args:\n%s' % (type(ex).__name__, ex.args))
|
||||
return ret
|
||||
|
||||
|
||||
sensors = get_sensors()
|
||||
sensor = next(iter(sensors), None)
|
||||
|
||||
# external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
|
||||
external_stylesheets = [dbc.themes.BOOTSTRAP]
|
||||
meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}]
|
||||
|
||||
app = dash.Dash(__name__, external_stylesheets=external_stylesheets, meta_tags=meta_tags)
|
||||
app.title = "dashboard.ykonni.de"
|
||||
|
||||
available_sensors = ["undefined"]
|
||||
|
||||
app.layout = html.Div(children=[
|
||||
html.H1(children='dashboard.ykonni.de'),
|
||||
|
@ -24,62 +51,121 @@ app.layout = html.Div(children=[
|
|||
html.Div(children='''
|
||||
visualize sensor data
|
||||
'''),
|
||||
dbc.Row([
|
||||
dbc.Col(
|
||||
dcc.Graph(
|
||||
id='example-graph',
|
||||
id='graph-sensor-values',
|
||||
figure={
|
||||
'data': [
|
||||
{'x': x, 'y': y, 'mode': 'markers', 'name': 'SF'}
|
||||
{'x': [0], 'y': [0], 'mode': 'markers', 'name': 'None'}
|
||||
],
|
||||
'layout': {
|
||||
'title': 'initial values'
|
||||
}
|
||||
}
|
||||
),
|
||||
)
|
||||
)
|
||||
]),
|
||||
dbc.Row([
|
||||
dbc.Col([
|
||||
html.Div(id='select-sensor-txt'),
|
||||
dcc.Dropdown(
|
||||
id='select-sensor',
|
||||
options=[{'label': i, 'value': i} for i in available_sensors],
|
||||
value="undefined"
|
||||
id='select-sensorid',
|
||||
options=[{'label': sensors[i]["sensorType"], 'value': i} for i in sensors],
|
||||
value=sensor),
|
||||
]),
|
||||
dbc.Col([
|
||||
html.Div(id='slider-min-txt'),
|
||||
dcc.Slider(
|
||||
id='slider-min',
|
||||
min=0,
|
||||
max=round(time.time()),
|
||||
step=600,
|
||||
value=0
|
||||
),
|
||||
html.Button(id='refresh-button', n_clicks=0, children='refresh')
|
||||
]),
|
||||
dbc.Col([
|
||||
html.Div(id='slider-max-txt'),
|
||||
dcc.Slider(
|
||||
id='slider-max',
|
||||
min=0,
|
||||
max=round(time.time()),
|
||||
step=600,
|
||||
value=round(time.time())
|
||||
),
|
||||
]),
|
||||
dbc.Col([
|
||||
html.Div(id='slider-limit-txt'),
|
||||
dcc.Slider(
|
||||
id='slider-limit',
|
||||
min=0,
|
||||
max=1000,
|
||||
step=10,
|
||||
value=0,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
])
|
||||
|
||||
@app.callback(
|
||||
[Output('slider-min', 'min'), Output('slider-min', 'value'),
|
||||
Output('slider-max', 'min'), Output('select-sensor-txt', 'children')],
|
||||
[Input('select-sensorid', 'value')])
|
||||
def update_slider_min(sensorId):
|
||||
res = get_values(sensorId, 0, int(time.time()), 1)
|
||||
min_ts = 0
|
||||
sensorType = None
|
||||
if "values" in res:
|
||||
min_ts = int(res["values"][0]["ts"])
|
||||
sensorType = res["sensorType"]
|
||||
|
||||
return min_ts, min_ts, min_ts, "Sensor: %s" % sensorType
|
||||
|
||||
@app.callback(
|
||||
Output('select-sensor', 'options'),
|
||||
[Input('refresh-button', 'n_clicks')])
|
||||
def update_list(n_clicks):
|
||||
url = "%s/sensor/get" % URL_BASE
|
||||
print(url)
|
||||
res = requests.get(url)
|
||||
content = res.json()
|
||||
options = [{'label': content[i]["sensorType"], 'value': i} for i in content]
|
||||
return options
|
||||
Output('slider-limit-txt', 'children'),
|
||||
[Input('slider-limit', 'value')])
|
||||
def update_slider_limit(value):
|
||||
return "Limit: %s" % (value if value > 0 else None)
|
||||
|
||||
|
||||
@app.callback(
|
||||
Output('example-graph', 'figure'),
|
||||
[Input('refresh-button', 'n_clicks'), Input('select-sensor', 'value')])
|
||||
def update_graph(n_clicks, sensorId):
|
||||
if not sensorId == "undefined":
|
||||
# url = "%s/sensor/get_values/%s?limit=10" % (URL_BASE, sensorId)
|
||||
url = "%s/sensor/get_values/%s" % (URL_BASE, sensorId)
|
||||
res = requests.get(url)
|
||||
content = res.json()
|
||||
v = content[sensorId]["values"]
|
||||
sensorType = content[sensorId]["sensorType"]
|
||||
Output('slider-min-txt', 'children'),
|
||||
[Input('slider-min', 'value')])
|
||||
def update_slider_min(value):
|
||||
return "From: %s" % (time.strftime("%Y/%m/%d %H:%M", time.localtime(float(value))) if
|
||||
value > 0 else 0)
|
||||
|
||||
|
||||
@app.callback(
|
||||
Output('slider-max-txt', 'children'),
|
||||
[Input('slider-max', 'value')])
|
||||
def update_slider_max(value):
|
||||
return "To: %s" % (time.strftime("%Y/%m/%d %H:%M", time.localtime(float(value))))
|
||||
|
||||
|
||||
@app.callback(
|
||||
Output('graph-sensor-values', 'figure'),
|
||||
[Input('select-sensorid', 'value'), Input('slider-min', 'value'),
|
||||
Input('slider-max', 'value'), Input('slider-limit', 'value')])
|
||||
def update_graph_sensor_values(sensorId, min_ts, max_ts, limit):
|
||||
res = get_values(sensorId, min_ts, max_ts, limit)
|
||||
if "values" in res:
|
||||
v = res["values"]
|
||||
s = res["sensorType"]
|
||||
l = len(v)
|
||||
x = [time.strftime("%m%d-%H%M", time.localtime(float(v[i]["ts"]))) for i in range(len(v))]
|
||||
y = [v[i]["value"] for i in range(len(v))]
|
||||
else:
|
||||
sensorType = sensorId
|
||||
x = [1]
|
||||
y = [1]
|
||||
s = sensorId
|
||||
x = [0]
|
||||
y = [0]
|
||||
|
||||
return {
|
||||
'data': [
|
||||
{'x': x, 'y': y, 'mode': 'markers', 'name': "%s" % (sensorType)}
|
||||
{'x': x, 'y': y, 'mode': 'markers', 'name': "%s" % (s)}
|
||||
],
|
||||
'layout': {
|
||||
'title': 'Data for sensor: %s' % (sensorType)
|
||||
'title': 'Data for sensor: %s (%d elements)' % (s, l)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue