This commit is contained in:
Dirk Alders 2025-07-19 20:07:17 +02:00
parent 68e5dfc073
commit 745e8e9524

View File

@ -7,26 +7,27 @@ import time
from textual.app import App, ComposeResult
from textual.containers import Vertical
from textual.widgets import Footer, Header, Input, RichLog, Checkbox
from textual.widgets import Footer, Header, Input, RichLog
class LogReceiver(object):
"""Ein Thread, der auf eingehende Log-Nachrichten lauscht."""
# TODO: Usage of multiple regex for topic filter
# TODO: Integrate sending of message (topic + payload)
class MqttReceiver(object):
def __init__(self, app):
self.app = app
args = app.args
password = app.password
self.mqtt_client = mqtt.mqtt_client('mqttsniffer', args.hostname, args.port, username=args.username, password=password)
self.mqtt_client = mqtt.mqtt_client('mqtt_sniffer', args.hostname, args.port, username=args.username, password=password)
self.mqtt_client.add_callback("#", self.__rx__)
def __rx__(self, client, userdata, message):
self.app.call_from_thread(self.app.add_log, message)
class LogViewerApp(App):
"""Eine Textual-App zum Anzeigen und Filtern von Python-Logs."""
class MqttSniffer(App):
"""a textual application for viewing mqtt messages."""
CSS_PATH = "style.tcss"
BINDINGS = [("q", "quit", "Quit")]
@ -42,7 +43,7 @@ class LogViewerApp(App):
self.log_display = RichLog(highlight=True, markup=True)
def compose(self) -> ComposeResult:
"""Erstellt die Widgets für die App."""
"""Create the widgets for the application."""
yield Header(name="Python Log Viewer")
with Vertical(id="app-grid"):
yield self.log_display
@ -51,11 +52,11 @@ class LogViewerApp(App):
yield Footer()
def on_mount(self) -> None:
"""Startet den Log-Empfänger-Thread."""
log_receiver = LogReceiver(self)
"""start the mqtt receiver."""
MqttReceiver(self)
def add_log(self, record) -> None:
"""Fügt einen neuen Log-Eintrag hinzu und aktualisiert die Anzeige."""
"""Add new mqt messages and update the tui."""
asctime = time.asctime()
self.all_logs.append((asctime, record))
if len(self.all_logs) > self.MAX_LOGS:
@ -64,13 +65,12 @@ class LogViewerApp(App):
def _apply_filters_to_log(self, data: logging.LogRecord):
asctime, record = data
"""Prüft einen einzelnen Log-Eintrag gegen die Filter und zeigt ihn ggf. an."""
"""filter the mqtt messages."""
topic_match = False
for topic_filter in self.topic_filter.split(","):
topic_match |= topic_filter.lower() in record.topic.lower()
if topic_match:
try:
payload = json.loads(record.payload)
except:
@ -85,20 +85,18 @@ class LogViewerApp(App):
self.log_display.write(message)
def _update_display(self):
"""Löscht die Anzeige und rendert alle Logs basierend auf den aktuellen Filtern neu."""
"""Clean the display and render all mqtt messages based on the current filters."""
self.log_display.clear()
for record in self.all_logs:
self._apply_filters_to_log(record)
def on_input_changed(self, message: Input.Changed) -> None:
"""Aktualisiert die Filter und die Anzeige, wenn der Benutzer tippt."""
"""Update the filter and filtered messages after the user did changes."""
if message.input.id == "topic_filter":
self.topic_filter = message.value
self._update_display()
self._update_display()
if __name__ == "__main__":
#
@ -128,5 +126,5 @@ if __name__ == "__main__":
#
# Start Application
#
app = LogViewerApp(args, password)
app = MqttSniffer(args, password)
app.run()