From 28ea71b647e1e40bc4701d9f8b7beda2540dfd68 Mon Sep 17 00:00:00 2001
From: rschoene <rene.schoene@tu-dresden.de>
Date: Tue, 22 Jun 2021 19:37:43 +0200
Subject: [PATCH] add filtering

---
 main.py  | 90 ++++++++++++++++++++++++++++++++++++++------------------
 utils.py |  9 +++++-
 2 files changed, 69 insertions(+), 30 deletions(-)

diff --git a/main.py b/main.py
index 0fbed9f..6902331 100644
--- a/main.py
+++ b/main.py
@@ -81,6 +81,7 @@ conversion_topics = {
     'place-b/command': (cgv_connector_pb2.MergedSelection(), utils.format_command),
     'place-b/reachability/arm1': (cgv_connector_pb2.Reachability(), utils.format_reachability),
     'place-b/reachability/arm2': (cgv_connector_pb2.Reachability(), utils.format_reachability),
+    'place-b/reachability/arm3': (cgv_connector_pb2.Reachability(), utils.format_reachability),
 }
 
 bytes_topics = [
@@ -174,7 +175,20 @@ app.layout = html.Div([
         html.Button('Dummy Ready', id='send-dummy-ready', style=button_style_normal),
     ], className='row'),
     # dcc.Markdown("---"),
-    html.H3("MQTT Log"),
+    html.H2("Filtered MQTT Log"),
+    dcc.Textarea(
+        id='filtered-mqtt-log',
+        value="",
+        readOnly=True,
+        style={**textarea_style_normal, 'height': '400px', 'fontFamily': 'Consolas, monospace'}
+    ),
+    dcc.Checklist(
+        id='topics-to-filter',
+        options=[{'label': topic, 'value': topic} for topic in conversion_topics],
+        value=[topic for topic in conversion_topics],
+        labelStyle={'display': 'inline-block'}
+    ),
+    html.H2("MQTT Log"),
     dcc.Textarea(
         id='mqtt-log',
         value="",
@@ -300,20 +314,29 @@ def send_complex(*_):
 
 
 @app.callback(
+    Output('filtered-mqtt-log', 'value'),
     Output('mqtt-log', 'value'),
     Output('javascriptLog', 'run'),
+    Output('topics-to-filter', 'options'),
     Input('every-1-second', 'n_intervals'),
     Input('clear-mqtt-log', 'n_clicks'),
+    Input('topics-to-filter', 'options'),
+    Input('topics-to-filter', 'value'),
+    State('filtered-mqtt-log', 'value'),
     State('mqtt-log', 'value'),
     State('should-scroll-mqtt-log', 'value')
 )
-def append_to_mqtt_log(_n_intervals, clear_n_clicks, value, should_scroll):
+def append_to_mqtt_log(_n_intervals, clear_n_clicks, filter_options, topics_to_filter,
+                       filtered_value, value, should_scroll):
     """
     Periodically update mqtt log
-    :param _n_intervals: Unused value of intervals
-    :param clear_n_clicks: clear.n_clicks
-    :param value: current content of mqtt log
-    :param should_scroll: checkbox value whether to scroll to the end after update
+    :param (Input) _n_intervals: Unused value of intervals
+    :param (Input) clear_n_clicks: clear.n_clicks
+    :param (Input) filter_options: displayed topics to show in filtered log
+    :param (Input) topics_to_filter: topics to show in filtered log
+    :param (State) value: current content of mqtt log
+    :param (State) filtered_value: current content of filtered mqtt log
+    :param (State) should_scroll: checkbox value whether to scroll to the end after update
     :return: new content of mqtt log
     """
     ctx = dash.callback_context
@@ -322,34 +345,43 @@ def append_to_mqtt_log(_n_intervals, clear_n_clicks, value, should_scroll):
 
     trigger_id = ctx.triggered[0]['prop_id'].split('.')[0]
     if trigger_id == 'clear-mqtt-log':
-        return "", ""
-
-    # assume trigger_id == 'every-1-second'
-    local_messages = []
-    while not message_queue.empty():
-        local_messages.append(message_queue.get_nowait())
-    if local_messages:
-        if value:
-            value += "\n"
-        else:
-            value = ""
-        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 "", "", "", filter_options
+
+    if trigger_id == 'topics-to-filter':
+        filtered_value = ""
+        for line in value.split('\n'):
+            if utils.topic_match(topics_to_filter, line):
+                filtered_value += line + '\n'
     else:
-        return dash.no_update
+        # assume trigger_id == 'every-1-second'
+        local_messages = []
+        while not message_queue.empty():
+            local_messages.append(message_queue.get_nowait())
+        if local_messages:
+            if value:
+                value += "\n"
+            else:
+                value = ""
+            value += '\n'.join(local_messages)
+            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
+                if topic_match:
+                    filtered_value += msg + "\n"
+                if topic not in filter_options:
+                    filter_options.append({'label': topic, 'value': topic})
+        else:
+            return dash.no_update
     log_cmd = '''
+             var filtered_textarea = document.getElementById('filtered-mqtt-log');
+             filtered_textarea.scrollTop = filtered_textarea.scrollHeight;
              var textarea = document.getElementById('mqtt-log');
              textarea.scrollTop = textarea.scrollHeight;
              ''' if should_scroll else ""
-    return value, log_cmd
+    return filtered_value, value, log_cmd, filter_options
 
 
 @app.callback(
diff --git a/utils.py b/utils.py
index 89fc487..d4bcf48 100644
--- a/utils.py
+++ b/utils.py
@@ -30,12 +30,19 @@ def format_log_msg(topic: str, max_mqtt_topic_length: int, message: str, timesta
 
 
 def parse_log_msg(entry: str):
-    print("Parsing >", entry, "<")
+    # print("Parsing >", entry, "<")
     at_index = entry.index('@')
     bracket_index = entry.index(']')
     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)
+    # replacing strange space characters
+    topic = topic.replace(chr(65532), '')
+    return topic in topics_to_filter
+
+
 def format_scene(scene: cgv_connector_pb2.Scene):
     result = ""
     for obj in scene.objects:
-- 
GitLab