From 75e003ba1c63a9403d3fe5f20545b900a64b1f89 Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Wed, 14 Jul 2021 19:04:35 +0200 Subject: [PATCH] allow reconnection to mqtt broker - also rearranged coordinator controls, and fixed topic filtering --- main.py | 91 ++++++++++++++++++++++++++++++++++++-------------------- utils.py | 9 ++++-- 2 files changed, 65 insertions(+), 35 deletions(-) diff --git a/main.py b/main.py index 6902331..2ceea6b 100644 --- a/main.py +++ b/main.py @@ -29,9 +29,6 @@ max_topic = utils.MaxTopicLength() # buffer for mqtt log message_queue = queue.Queue() -# remember how often clear button was pressed (to only trigger clearing once) -last_clear_n_clicks = 0 - # button-id: (topic, payload) commands = { 'send-place-a-model': ('place-a/model', '1'), @@ -137,6 +134,28 @@ app.layout = html.Div([ ], className='row', style={'display': 'none'}), # dcc.Markdown("---"), html.Div([ # Row for commands + html.Div([ # Column for commands of place b + html.H3("Coordinator"), + # html.Div([ # Row for commands coordinator + html.Button('Model', id='send-coordinator-model', style=button_style_normal), + html.Button('Model (Details)', id='send-coordinator-model-details', style=button_style_normal), + html.Button('Exit', id='send-coordinator-exit', style=button_style_exit), + # ], className='row'), + # html.Div([ # Row for commands up + html.Button('Robot Control A Up', id='send-place-a-robot-ctrl-up', style=button_style_normal), + html.Button('Robot Control B Up', id='send-place-b-robot-ctrl-up', style=button_style_normal), + html.Button('RAG A Up', id='send-place-a-rag-up', style=button_style_normal), + html.Button('RAG B Up', id='send-place-b-rag-up', style=button_style_normal), + html.Button('Dummy Up', id='send-dummy-up', style=button_style_normal), + # ], className='row'), + # html.Div([ # Row for commands ready + html.Button('Robot Control A Ready', id='send-place-a-robot-ctrl-ready', style=button_style_normal), + html.Button('Robot Control B Ready', id='send-place-b-robot-ctrl-ready', style=button_style_normal), + html.Button('RAG A Ready', id='send-place-a-rag-ready', style=button_style_normal), + html.Button('RAG B Ready', id='send-place-b-rag-ready', style=button_style_normal), + html.Button('Dummy Ready', id='send-dummy-ready', style=button_style_normal), + # ], className='row'), + ], className="four columns"), html.Div([ # Column for commands of place a html.H3("Commands Place A"), html.Button('Model', id='send-place-a-model', style=button_style_normal), @@ -145,7 +164,7 @@ app.layout = html.Div([ html.Button('Exit', id='send-place-a-exit', style=button_style_exit), html.Button('obj-Red -> Red', id='send-place-a-demo-objRed-red', style=button_style_normal), html.Button('obj-Red -> Blue', id='send-place-a-demo-objRed-blue', style=button_style_normal), - ], className="six columns"), + ], className="four columns"), html.Div([ # Column for commands of place b html.H3("Commands Place B"), html.Button('Model', id='send-place-b-model', style=button_style_normal), @@ -153,26 +172,7 @@ app.layout = html.Div([ html.Button('Rewind', id='send-place-b-rewind', style=button_style_normal), html.Button('Exit', id='send-place-b-exit', style=button_style_exit), html.Button('obj-Red -> Red', id='send-place-b-demo-objRed-red', style=button_style_normal), - ], className="six columns"), - ], className='row'), - html.Div([ # Row for commands coordinator - html.Button('Coordinator Model', id='send-coordinator-model', style=button_style_normal), - html.Button('Coordinator Model (Details)', id='send-coordinator-model-details', style=button_style_normal), - html.Button('Coordinator Exit', id='send-coordinator-exit', style=button_style_exit), - ], className='row'), - html.Div([ # Row for commands up - html.Button('Robot Control A Up', id='send-place-a-robot-ctrl-up', style=button_style_normal), - html.Button('Robot Control B Up', id='send-place-b-robot-ctrl-up', style=button_style_normal), - html.Button('RAG A Up', id='send-place-a-rag-up', style=button_style_normal), - html.Button('RAG B Up', id='send-place-b-rag-up', style=button_style_normal), - html.Button('Dummy Up', id='send-dummy-up', style=button_style_normal), - ], className='row'), - html.Div([ # Row for commands ready - html.Button('Robot Control A Ready', id='send-place-a-robot-ctrl-ready', style=button_style_normal), - html.Button('Robot Control B Ready', id='send-place-b-robot-ctrl-ready', style=button_style_normal), - html.Button('RAG A Ready', id='send-place-a-rag-ready', style=button_style_normal), - html.Button('RAG B Ready', id='send-place-b-rag-ready', style=button_style_normal), - html.Button('Dummy Ready', id='send-dummy-ready', style=button_style_normal), + ], className="four columns"), ], className='row'), # dcc.Markdown("---"), html.H2("Filtered MQTT Log"), @@ -201,6 +201,12 @@ app.layout = html.Div([ value=["Auto-Scroll"], labelStyle={"display": "inline-block"}, ), + dcc.Checklist( + id="mqtt-connected", + options=[{"label": "MQTT connected?", "value": "yes", "disabled": True}], + value=[], + labelStyle={"display": "inline-block"}, + ), html.Button('Clear log', id='clear-mqtt-log', style=button_style_normal), dcc.Markdown("---"), html.Div([ @@ -313,6 +319,17 @@ def send_complex(*_): return dash.no_update +@app.callback( + Output('mqtt-connected', 'value'), + Input('every-1-second', 'n_intervals'), +) +def check_connection(_n_intervals): + if not ready_event.is_set(): + print('.', end='', flush=True) + return [] + return ['yes'] + + @app.callback( Output('filtered-mqtt-log', 'value'), Output('mqtt-log', 'value'), @@ -349,9 +366,13 @@ def append_to_mqtt_log(_n_intervals, clear_n_clicks, filter_options, topics_to_f if trigger_id == 'topics-to-filter': filtered_value = "" + last_match = True for line in value.split('\n'): - if utils.topic_match(topics_to_filter, line): + if utils.topic_match(topics_to_filter, line, last_match=last_match)[0]: filtered_value += line + '\n' + last_match = True + else: + last_match = False else: # assume trigger_id == 'every-1-second' local_messages = [] @@ -366,12 +387,10 @@ def append_to_mqtt_log(_n_intervals, clear_n_clicks, filter_options, topics_to_f if not filtered_value: filtered_value = "" for msg in local_messages: - timestamp, topic, message = utils.parse_log_msg(msg) - topic = topic.replace(chr(65532), '') - topic_match = topic in topics_to_filter + topic_match, topic = utils.topic_match(topics_to_filter, msg) if topic_match: filtered_value += msg + "\n" - if topic not in filter_options: + if topic not in (option['label'] for option in filter_options): filter_options.append({'label': topic, 'value': topic}) else: return dash.no_update @@ -427,8 +446,15 @@ def send_manual(n_clicks, topic, message): def on_mqtt_connect(_client, _userdata, _flags, _rc, _properties=None): # Callback for mqtt client when connected - print('Connected at ' + datetime.datetime.now().isoformat()) + print('\nConnected at ' + datetime.datetime.now().isoformat()) ready_event.set() + mqttc.subscribe(topic='#') + threading.Thread(target=publish_test_message).start() + + +def on_mqtt_disconnect(_client, _userdata, _rc): + print('Lost connection at ' + datetime.datetime.now().isoformat()) + ready_event.clear() def on_mqtt_message(_client, _userdata, message): @@ -463,12 +489,13 @@ def publish_test_message(): if __name__ == '__main__': + print('Starting web-ros3rag') mqttc.on_connect = on_mqtt_connect + mqttc.on_disconnect = on_mqtt_disconnect mqttc.on_message = on_mqtt_message + mqttc.reconnect_delay_set(max_delay=2) mqttc.connect_async(MQTT_SERVER) mqttc.loop_start() if not ready_event.wait(2.0): # wait 2 seconds print('Could not connect to mqtt in time!') - mqttc.subscribe(topic='#') - threading.Thread(target=publish_test_message).start() app.run_server(debug=True) diff --git a/utils.py b/utils.py index d4bcf48..b3751da 100644 --- a/utils.py +++ b/utils.py @@ -36,11 +36,14 @@ def parse_log_msg(entry: str): return entry[1:at_index].strip(), entry[at_index + 1:bracket_index].strip(), entry[bracket_index + 2:] -def topic_match(topics_to_filter, msg): - timestamp, topic, message = parse_log_msg(msg) +def topic_match(topics_to_filter, msg, last_match=True): + try: + timestamp, topic, message = parse_log_msg(msg) + except: + return last_match, None # replacing strange space characters topic = topic.replace(chr(65532), '') - return topic in topics_to_filter + return topic in topics_to_filter, topic def format_scene(scene: cgv_connector_pb2.Scene): -- GitLab