From b84d2ce1fbf92fd555e36b3f2c680c05d72a7378 Mon Sep 17 00:00:00 2001 From: Konstantin Koslowski Date: Mon, 2 Mar 2020 00:42:58 +0100 Subject: [PATCH] homecontrol-dash: fix/merge callbacks --- homecontrol_dash/hcdash.py | 227 ++++++++++++++++++++++++++----------- 1 file changed, 160 insertions(+), 67 deletions(-) diff --git a/homecontrol_dash/hcdash.py b/homecontrol_dash/hcdash.py index d282ab2..6dc8afb 100755 --- a/homecontrol_dash/hcdash.py +++ b/homecontrol_dash/hcdash.py @@ -109,7 +109,7 @@ class HCDash: self.logger.debug(f"set_level: {req}") requests.post(f"{self.config.get('address')}/actor/command", json=req) - def get_values(self, sensorId, min_ts, max_ts, limit): + def get_sensor_values(self, sensorId, min_ts, max_ts, limit): ret = {} if sensorId: try: @@ -120,6 +120,18 @@ class HCDash: self.logger.error(f"Exception Type: {type(ex).__name__}, args:\n{ex.args}") return ret + def get_actor_levels(self, actorId, min_ts, max_ts, limit): + self.logger.debug(f"get_actor_levels: {actorId}") + ret = {} + if actorId: + try: + url = f"{self.config.get('address')}/actor/get_levels/{actorId}?min_ts={min_ts}&max_ts={max_ts}&limit={limit}" + res = requests.get(url) + ret = res.json()[actorId] + except Exception as ex: + self.logger.error(f"Exception Type: {type(ex).__name__}, args:\n{ex.args}") + return ret + def pTime(self, value, fmt="%Y/%m/%d %H:%M"): if value > 0: @@ -181,9 +193,7 @@ class HCDash: dbc.Col(dcc.Tabs(id="tabs-select-actor", value=actor, children=actor_tabs)) ]), - dbc.Row([ - html.Div(id="actor-data"), - ]), + html.Div(id="actor-data"), ]) else: return html.Div([ @@ -191,12 +201,15 @@ class HCDash: ]), None, None @app.callback( - Output("sensor-data", "children"), + [Output("sensor-data", "children"), + Output('slider-min', 'min'), Output('slider-min', 'value'), + Output('slider-min', 'max'), Output('slider-max', 'min'), + Output('slider-max', 'value'), Output('slider-max', 'max')], [Input("tabs-select-sensor", "value")]) - def update_sensor(value): - self.logger.debug(f"update_sensor: {value}") - if value: - return [ + def update_sensor(sensorId): + self.logger.debug(f"update_sensor: {sensorId}") + if sensorId: + sensor_data = [ dbc.Row([ dbc.Col( dcc.Graph( @@ -215,8 +228,8 @@ class HCDash: dcc.Slider(id='slider-min', min=0, max=round(time.time()), step=600, value=0 ), ], style={'marginLeft': '5em', 'marginRight': '3em'} - ), - ]), + ), + ]), dbc.Col([ html.Div(id='slider-max-txt', style={'marginLeft': '3em', 'marginRight': '3em'}), @@ -224,52 +237,28 @@ class HCDash: dcc.Slider(id='slider-max', min=0, max=round(time.time()), step=600, value=round(time.time())), ], style={'marginLeft': '3em', 'marginRight': '3em'} - ), - ]), + ), + ]), dbc.Col([ html.Div(id='slider-limit-txt', style={'marginLeft': '3em', 'marginRight': '5em'}), html.Div([ dcc.Slider(id='slider-limit', min=0, max=1000, step=10, value=0 ), ], style={'marginLeft': '3em', 'marginRight': '5em'} - ), - ]) - ]), - ] - - @app.callback( - Output("actor-data", "children"), - [Input("tabs-select-actor", "value")]) - def update_actor(value): - self.logger.debug(f"update_actor: {value}") - if value: - return [ - daq.ColorPicker( - id="color-picker", - label="Color Picker", - size=360, - value=dict(hex="#268bd2") ), - html.P(id="empty") - ] + ]) + ]), + ] + res = self.get_sensor_values(sensorId, 0, int(time.time()), 1) + min_ts = 0 + # default last 7 days + cur_ts = round(time.time() - (60*60*24*7)) + max_ts = int(time.time()) + if "values" in res: + min_ts = int(res["values"][0]["ts"]) + # sensor_data, min: [min, cur, max], max: [min, max, max] + return sensor_data, min_ts, cur_ts, max_ts, min_ts, max_ts, max_ts - ## sensor callbacks - @app.callback( - [Output('slider-min', 'min'), Output('slider-min', 'value'), - Output('slider-min', 'max')], - [Input('tabs-select-sensor', 'value')]) - def update_slider_min(sensorId): - res = self.get_values(sensorId, 0, int(time.time()), 1) - min_ts = 0 - # default last 7 days - cur_ts = round(time.time() - (60*60*24*7)) - max_ts = int(time.time()) - sensorType = None - if "values" in res: - min_ts = int(res["values"][0]["ts"]) - sensorType = res["sensorType"] - return min_ts, cur_ts, max_ts - @app.callback( Output('slider-min-txt', 'children'), [Input('slider-min', 'value')]) @@ -277,21 +266,6 @@ class HCDash: return f"From: {self.pTime(value)}" - @app.callback( - [Output('slider-max', 'min'), Output('slider-max', 'value'), - Output('slider-max', 'max')], - [Input('tabs-select-sensor', 'value')]) - def update_slider_max(sensorId): - res = self.get_values(sensorId, 0, int(time.time()), 1) - min_ts = 0 - max_ts = int(time.time()) - sensorType = None - if "values" in res: - min_ts = int(res["values"][0]["ts"]) - sensorType = res["sensorType"] - return min_ts, max_ts, max_ts - - @app.callback( Output('slider-max-txt', 'children'), [Input('slider-max', 'value')]) @@ -313,7 +287,7 @@ class HCDash: def update_graph_sensor_values(sensorId, min_ts, max_ts, limit): res = {} if min_ts > 0: - res = self.get_values(sensorId, min_ts, max_ts, limit) + res = self.get_sensor_values(sensorId, min_ts, max_ts, limit) if "values" in res: v = res["values"] s = res["sensorType"] @@ -333,16 +307,135 @@ class HCDash: ## actor callbacks + @app.callback( + [Output("actor-data", "children"), + Output("slider-actor-min", "min"), Output("slider-actor-min", "value"), + Output("slider-actor-min", "max"), Output("slider-actor-max", "min"), + Output("slider-actor-max", "value"), Output("slider-actor-max", "max")], + [Input("tabs-select-actor", "value")]) + def update_actor(actorId): + self.logger.debug(f"update_actor: {actorId}") + if actorId: + res = self.get_actors() + l = res[actorId].get("level") or 0 + level = f"#{format(l, '06x')}" + actor_data = [ + dbc.Row([ + dbc.Col( + dcc.Graph( + id='graph-actor-values', + figure={ + 'data': [ {'x': [0], 'y': [0], 'mode': 'line', 'name': 'None'} ], + 'layout': { 'title': 'initial values' } + } + ) + ) + ]), + dbc.Row([ + dbc.Col([ + html.Div(id='slider-actor-min-txt', style={'marginLeft': '5em', 'marginRight': '3em'}), + html.Div([ + dcc.Slider(id='slider-actor-min', min=0, max=round(time.time()), step=600, + value=0 ), + ], style={'marginLeft': '5em', 'marginRight': '3em'} + ), + ]), + dbc.Col([ + html.Div(id='slider-actor-max-txt', style={'marginLeft': '3em', 'marginRight': + '3em'}), + html.Div([ + dcc.Slider(id='slider-actor-max', min=0, max=round(time.time()), step=600, + value=round(time.time())), + ], style={'marginLeft': '3em', 'marginRight': '3em'} + ), + ]), + dbc.Col([ + html.Div(id='slider-actor-limit-txt', style={'marginLeft': '3em', 'marginRight': '5em'}), + html.Div([ + dcc.Slider(id='slider-actor-limit', min=0, max=1000, step=10, value=0 ), + ], style={'marginLeft': '3em', 'marginRight': '5em'} + ), + ]) + ]), + dbc.Row([ + daq.ColorPicker( + id="color-picker", + label="Color Picker", + size=360, + value=dict(hex=level) + ), + html.P(id="empty") + ]), + ] + res = self.get_actor_levels(actorId, 0, int(time.time()), 1) + min_ts = 0 + # default last 7 days + cur_ts = round(time.time() - (60*60*24*7)) + max_ts = int(time.time()) + if "levels" in res: + min_ts = int(res["levels"][0]["ts"]) + # actor_data, min: [min, cur, max], max: [min, max, max] + return actor_data, min_ts, cur_ts, max_ts, min_ts, max_ts, max_ts + + + @app.callback( + Output('slider-actor-min-txt', 'children'), + [Input('slider-actor-min', 'value')]) + def update_slider_actor_min_txt(value): + # self.logger.debug(f"update_slider_actor_min_txt: {value}") + return f"From: {self.pTime(value)}" + + + @app.callback( + Output('slider-actor-max-txt', 'children'), + [Input('slider-actor-max', 'value')]) + def update_slider_actor_max_txt(value): + # self.logger.debug(f"update_slider_actor_max_txt: {value}") + return f"To: {self.pTime(value)}" + + + @app.callback( + Output('slider-actor-limit-txt', 'children'), + [Input('slider-actor-limit', 'value')]) + def update_slider_actor_limit_txt(value): + return f"Limit: {value if value > 0 else None}" + + @app.callback( Output("empty", "value"), - [Input('tabs-select-actor', 'value'), Input('color-picker', 'value')]) + [Input("tabs-select-actor", "value"), Input("color-picker", "value")]) def set_level(actorId, level): l = f"0x{level.get('hex').replace('#', '')}" if l: self.set_level(actorId, l) - self.logger.debug(f"hex: {l}") return "" + @app.callback( + Output('graph-actor-values', 'figure'), + [Input('tabs-select-actor', 'value'), Input('slider-actor-min', 'value'), + Input('slider-actor-max', 'value'), Input('slider-actor-limit', 'value')]) + def update_graph_actor(actorId, min_ts, max_ts, limit): + self.logger.debug(f"update_graph_actor: {actorId}, {min_ts}, {max_ts}, {limit}") + res = {} + if min_ts > 0: + res = self.get_actor_levels(actorId, min_ts, max_ts, limit) + if "levels" in res: + v = res["levels"] + s = res["actorType"] + x = [self.pTime(v[i]["ts"], fmt="%m%d-%H%M") for i in range(len(v))] + y = [v[i]["value"] for i in range(len(v))] + # y = [[(int(v[i]["value"]) >> 16) & 0xff, (int(v[i]["value"]) >> 8) & 0xff, + # int(v[i]["value"]) & 0xff] for i in range(len(v))] + else: + s = actorId + x = [0] + y = [0] + return { + 'data': [ {'x': x, 'y': y, 'mode': 'markers', 'name': f'{s}'} ], + 'layout': { 'title': f'Data for sensor: {s} ({len(x)} elements)' } + } + + app.run_server(host="0.0.0.0", port=self.config.get("port"), debug=self.config.get("debug"))