From f1b6b11db52cc141dfd3ec09fa8d8620360fe26b Mon Sep 17 00:00:00 2001 From: Konstantin Koslowski Date: Sun, 1 Mar 2020 22:30:35 +0100 Subject: [PATCH] homecontrol-dash: adapt layout for sensors or actors --- .gitignore | 1 + .../__pycache__/hcdash.cpython-38.pyc | Bin 9330 -> 0 bytes homecontrol_dash/hcdash.py | 101 +++++++++++------- 3 files changed, 62 insertions(+), 40 deletions(-) delete mode 100644 homecontrol_dash/__pycache__/hcdash.cpython-38.pyc diff --git a/.gitignore b/.gitignore index ba64065..47e3095 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ dash dcc poetry.lock homecontrol_dash.egg-info +__pycache__ diff --git a/homecontrol_dash/__pycache__/hcdash.cpython-38.pyc b/homecontrol_dash/__pycache__/hcdash.cpython-38.pyc deleted file mode 100644 index 0428126af69e429d42074d8d80caea2e807ee236..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9330 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 (time.time() - 60*10): + ret[a] = tmp[a] self.logger.debug(f"get_actors: {ret}") except Exception as ex: self.logger.error(f"Exception get_actors, type: {type(ex).__name__}, args:\n{ex.args}") @@ -146,11 +149,12 @@ class HCDash: ]), html.Div(id="tabs-content") ]) - + # tab callbacks @app.callback( Output("tabs-content", "children"), [Input("tabs-select-class", "value")]) - def updatefoo(value): + def update_tabs(value): + self.logger.debug(f"update_tabs: {value}") if value == "sensors": sensors = self.get_sensors() sensor = next(iter(sensors), None) @@ -163,6 +167,36 @@ class HCDash: dbc.Col(dcc.Tabs(id="tabs-select-sensor", value=sensor, children=sensor_tabs)) ]), + html.Div(id="sensor-data"), + ]) + elif value == "actors": + actors = self.get_actors() + actor = next(iter(actors), None) + actor_tabs = [] + for a in actors: + actorType = actors[a]["actorType"] + actor_tabs.append(dcc.Tab(label=actorType, value=a)) + return html.Div([ + dbc.Row([ + dbc.Col(dcc.Tabs(id="tabs-select-actor", value=actor, + children=actor_tabs)) + ]), + dbc.Row([ + html.Div(id="actor-data"), + ]), + ]) + else: + return html.Div([ + html.H3("undefined") + ]), None, None + + @app.callback( + Output("sensor-data", "children"), + [Input("tabs-select-sensor", "value")]) + def update_sensor(value): + self.logger.debug(f"update_sensor: {value}") + if value: + return [ dbc.Row([ dbc.Col( dcc.Graph( @@ -181,8 +215,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'}), @@ -190,43 +224,33 @@ 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'} - ), + ), + ]) ]), - ]), - ]) - elif value == "actors": - actors = self.get_actors() - actor = next(iter(actors), None) - actor_tabs = [] - for a in actors: - actorType = actors[a]["actorType"] - actor_tabs.append(dcc.Tab(label=actorType, value=a)) - return html.Div([ - dbc.Row([ - dbc.Col(dcc.Tabs(id="tabs-select-actor", value=actor, - children=actor_tabs)) - ]), - dbc.Row([ + ] + + @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=400, + size=360, value=dict(hex="#268bd2") ), html.P(id="empty") - ]), - ]) - else: - return html.Div([ - html.H3("undefined") - ]) + ] ## sensor callbacks @@ -244,7 +268,6 @@ class HCDash: if "values" in res: min_ts = int(res["values"][0]["ts"]) sensorType = res["sensorType"] - return min_ts, cur_ts, max_ts @app.callback( @@ -253,6 +276,7 @@ class HCDash: def update_slider_min_txt(value): return f"From: {self.pTime(value)}" + @app.callback( [Output('slider-max', 'min'), Output('slider-max', 'value'), Output('slider-max', 'max')], @@ -265,7 +289,6 @@ class HCDash: if "values" in res: min_ts = int(res["values"][0]["ts"]) sensorType = res["sensorType"] - return min_ts, max_ts, max_ts @@ -308,19 +331,17 @@ class HCDash: 'layout': { 'title': f'Data for sensor: {s} ({len(x)} elements)' } } + ## actor callbacks @app.callback( Output("empty", "value"), [Input('tabs-select-actor', 'value'), Input('color-picker', 'value')]) def set_level(actorId, level): - rgb = level.get("rgb") - if rgb: - r = (rgb.get("r") or 0) << 16 - g = (rgb.get("g") or 0) << 8 - b = (rgb.get("b") or 0) - l = r + g + b + l = f"0x{level.get('hex').replace('#', '')}" + if l: self.set_level(actorId, l) - return "" + self.logger.debug(f"hex: {l}") + return "" app.run_server(host="0.0.0.0", port=self.config.get("port"), debug=self.config.get("debug"))