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
 | 
			
		||||
    '''),
 | 
			
		||||
    dcc.Graph(
 | 
			
		||||
        id='example-graph',
 | 
			
		||||
        figure={
 | 
			
		||||
            'data': [
 | 
			
		||||
                {'x': x, 'y': y, 'mode': 'markers', 'name': 'SF'}
 | 
			
		||||
            ],
 | 
			
		||||
            'layout': {
 | 
			
		||||
                'title': 'initial values'
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    ),
 | 
			
		||||
    dcc.Dropdown(
 | 
			
		||||
        id='select-sensor',
 | 
			
		||||
        options=[{'label': i, 'value': i} for i in available_sensors],
 | 
			
		||||
        value="undefined"
 | 
			
		||||
    ),
 | 
			
		||||
    html.Button(id='refresh-button', n_clicks=0, children='refresh')
 | 
			
		||||
    dbc.Row([
 | 
			
		||||
        dbc.Col(
 | 
			
		||||
            dcc.Graph(
 | 
			
		||||
                id='graph-sensor-values',
 | 
			
		||||
                figure={
 | 
			
		||||
                    'data': [
 | 
			
		||||
                        {'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-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
 | 
			
		||||
            ),
 | 
			
		||||
        ]),
 | 
			
		||||
        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…
	
	Add table
		Add a link
		
	
		Reference in a new issue