Skip to content
Snippets Groups Projects
Commit d8239c61 authored by René Schöne's avatar René Schöne
Browse files

buttons are working, reformatting

- mqtt log adjusts to topic length
- split view into place-a and place-b
- scene/update not implemented yet
parent 07ada146
No related branches found
No related tags found
No related merge requests found
...@@ -3,7 +3,6 @@ import datetime ...@@ -3,7 +3,6 @@ import datetime
import queue import queue
import threading import threading
import time import time
from threading import Thread
import dash import dash
import dash_core_components as dcc import dash_core_components as dcc
...@@ -11,44 +10,77 @@ import dash_html_components as html ...@@ -11,44 +10,77 @@ import dash_html_components as html
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
from dash.dependencies import Input, Output, State from dash.dependencies import Input, Output, State
import utils
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
MQTT_SERVER = 'localhost' MQTT_SERVER = 'localhost'
mqttc = mqtt.Client() mqttc = mqtt.Client()
# mqtt client connected?
ready_event = threading.Event() ready_event = threading.Event()
# mqtt log reformat object
max_topic = utils.MaxTopicLength()
# buffer for mqtt log
message_queue = queue.Queue() message_queue = queue.Queue()
# button-id: (topic, payload)
commands = {
'send-place-a-model': ('place-a/model', '1'),
'send-place-a-exit': ('place-a/exit', '1'),
'send-place-b-model': ('place-b/model', '1'),
'send-place-b-exit': ('place-b/exit', '1'),
}
app = dash.Dash(__name__, external_stylesheets=external_stylesheets) app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([ app.layout = html.Div([
html.P("Send to scene/update"), html.Div([
html.Div([
dcc.Textarea( dcc.Textarea(
id='place-a-input-json', id='place-a-input-json',
placeholder='place-a-input-json', placeholder='place-a-input-json',
value='{}', value='{}',
style={'width': '100%'} style={'width': '100%'}
), ),
html.Button('Send', id='send-place-a-update'), html.Button('Send to place-a/scene/update', id='send-place-a-update'),
], className="six columns"),
html.Div([
dcc.Textarea(
id='place-b-input-json',
placeholder='place-b-input-json',
value='{}',
style={'width': '100%'}
),
html.Button('Send to place-b/scene/update', id='send-place-b-update'),
], className="six columns"),
], className='row'),
dcc.Markdown("---"), dcc.Markdown("---"),
html.H3("Commands"), html.H3("Commands"),
html.Div([
html.Div([
html.Button('Place A: Model', id='send-place-a-model', style={"margin-right": "15px"}), html.Button('Place A: Model', id='send-place-a-model', style={"margin-right": "15px"}),
html.Button('Place A: Exit', id='send-place-a-exit', style={"margin-right": "15px"}), html.Button('Place A: Exit', id='send-place-a-exit', style={"margin-right": "15px"}),
], className="six columns"),
html.Div([
html.Button('Place B: Model', id='send-place-b-model', style={"margin-right": "15px"}), html.Button('Place B: Model', id='send-place-b-model', style={"margin-right": "15px"}),
html.Button('Place B: Exit', id='send-place-b-exit', style={"margin-right": "15px"}), html.Button('Place B: Exit', id='send-place-b-exit', style={"margin-right": "15px"}),
], className="six columns"),
], className='row'),
dcc.Markdown("---"),
html.H3("MQTT Log"), html.H3("MQTT Log"),
dcc.Textarea( dcc.Textarea(
id='mqtt-log', id='mqtt-log',
readOnly=True, readOnly=True,
rows=50, rows=50,
style={'width': '100%', 'height': '200px'} style={'width': '100%', 'height': '200px', 'font-family': 'Consolas, monospace'}
), ),
dcc.Interval( dcc.Interval(
id='every-1-second', id='every-1-second',
interval=1000, # in milliseconds interval=1000, # in milliseconds
n_intervals=0 n_intervals=0
), ),
html.Button("add to mqtt log", id="add-to-mqtt-log"),
html.Div(id='hidden-div', style={'display': 'none'}) html.Div(id='hidden-div', style={'display': 'none'})
]) ])
...@@ -56,7 +88,7 @@ app.layout = html.Div([ ...@@ -56,7 +88,7 @@ app.layout = html.Div([
@app.callback( @app.callback(
Output('mqtt-log', 'value'), Output('mqtt-log', 'value'),
Input('every-1-second', 'n_intervals'), Input('every-1-second', 'n_intervals'),
State('mqtt-log', 'value') State('mqtt-log', 'value'),
) )
def append_to_mqtt_log(_, value): def append_to_mqtt_log(_, value):
local_messages = [] local_messages = []
...@@ -67,49 +99,63 @@ def append_to_mqtt_log(_, value): ...@@ -67,49 +99,63 @@ def append_to_mqtt_log(_, value):
value += "\n" value += "\n"
else: else:
value = "" value = ""
return value + ('\n'.join(local_messages)) value += '\n'.join(local_messages)
if max_topic.get_and_clear():
lines = value.split('\n')
reformatted_lines = []
for line in lines:
timestamp, topic, message = utils.parse_log_msg(line)
print(f'{timestamp, topic, message}')
reformatted_lines.append(utils.format_log_msg(topic, max_topic.max_mqtt_topic_length,
message, timestamp=timestamp))
value = '\n'.join(reformatted_lines)
return value return value
@app.callback( @app.callback(
Output('hidden-div', 'children'), Output('hidden-div', 'children'),
Input('add-to-mqtt-log', 'n_clicks'), Input('send-place-a-model', 'n_clicks'),
Input('send-place-a-exit', 'n_clicks'),
Input('send-place-b-model', 'n_clicks'),
Input('send-place-b-exit', 'n_clicks'),
) )
def button_clicked_to_add_to_mqtt_log(n_clicks): def button_clicked_to_add_to_mqtt_log(*_):
if n_clicks: ctx = dash.callback_context
print("button clicked")
message_queue.put_nowait("Button clicked " + str(n_clicks) + " times") if not ctx.triggered:
button_id = None
else:
button_id = ctx.triggered[0]['prop_id'].split('.')[0]
if button_id:
topic, payload = commands[button_id]
mqttc.publish(topic=topic, payload=payload)
return dash.no_update return dash.no_update
def on_mqtt_connect(client, userdata, flags, rc, properties=None): def on_mqtt_connect(_client, _userdata, _flags, _rc, _properties=None):
print('Connected at ' + datetime.datetime.now().isoformat()) print('Connected at ' + datetime.datetime.now().isoformat())
ready_event.set() ready_event.set()
def on_mqtt_message(client, userdata, message): def on_mqtt_message(_client, _userdata, message):
payload = message.topic + ": " + message.payload.decode('utf-8') max_mqtt_topic_length = max_topic.process_topic(message.topic)
print('Got mqtt message: ' + payload + ", userdata: " + str(userdata)) message_queue.put_nowait(utils.format_log_msg(message.topic,
message_queue.put_nowait(payload) max_mqtt_topic_length,
message.payload.decode("utf-8")))
def on_mqtt_subscribe(client, userdata, mid, granted_qos, properties=None):
print("Subscribed")
def publish_test_message(): def publish_test_message():
time.sleep(2) time.sleep(2)
mqttc.publish(topic="test", payload=datetime.datetime.now().isoformat()) mqttc.publish(topic="init", payload=datetime.datetime.now().isoformat())
if __name__ == '__main__': if __name__ == '__main__':
mqttc.on_connect = on_mqtt_connect mqttc.on_connect = on_mqtt_connect
mqttc.on_message = on_mqtt_message mqttc.on_message = on_mqtt_message
mqttc.on_subscribe = on_mqtt_subscribe
mqttc.connect_async(MQTT_SERVER) mqttc.connect_async(MQTT_SERVER)
mqttc.loop_start() mqttc.loop_start()
if not ready_event.wait(2.0): # wait 2 seconds if not ready_event.wait(2.0): # wait 2 seconds
print('Could not connect to mqtt in time!') print('Could not connect to mqtt in time!')
mqttc.subscribe(topic='#') mqttc.subscribe(topic='#')
Thread(target=publish_test_message).start() threading.Thread(target=publish_test_message).start()
app.run_server(debug=True) app.run_server(debug=True)
utils.py 0 → 100644
import threading
from datetime import datetime
class MaxTopicLength:
def __init__(self):
self.max_mqtt_topic_length = 1
self.mqtt_log_reformat_event = threading.Event()
def process_topic(self, topic):
if len(topic) > self.max_mqtt_topic_length:
self.max_mqtt_topic_length = len(topic)
print(f'new long topic length: {self.max_mqtt_topic_length}')
self.mqtt_log_reformat_event.set()
return self.max_mqtt_topic_length
def get_and_clear(self):
if self.mqtt_log_reformat_event.is_set():
self.mqtt_log_reformat_event.clear()
return True
return False
def format_log_msg(topic: str, max_mqtt_topic_length: int, message: str, timestamp: datetime = None):
now = timestamp or datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# padding = max_mqtt_topic_length - len(topic) + 1
return f'[{now} @ {topic:{max_mqtt_topic_length}}] {message}'
def parse_log_msg(entry: str):
at_index = entry.index('@')
closing_bracket_index = entry.index(']')
return entry[1:at_index].strip(), entry[at_index + 1:closing_bracket_index].strip(), entry[closing_bracket_index+2:]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment