From 43430b37258da44a2fd92b2fc8b8fdc5de73452f Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Sat, 23 Aug 2025 00:27:07 -0700 Subject: [PATCH] parse protobufs --- contact/ui/contact_ui.py | 10 ++++++---- contact/utilities/utils.py | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/contact/ui/contact_ui.py b/contact/ui/contact_ui.py index 995ac86..f9b5596 100644 --- a/contact/ui/contact_ui.py +++ b/contact/ui/contact_ui.py @@ -7,6 +7,7 @@ from typing import Union from contact.utilities.utils import get_channels, get_readable_duration, get_time_ago, refresh_node_list from contact.settings import settings_menu from contact.message_handlers.tx_handler import send_message, send_traceroute +from contact.utilities.utils import parse_protobuf from contact.ui.colors import get_color from contact.utilities.db_handler import get_name_from_database, update_node_info_in_db, is_chat_archived from contact.utilities.input_handlers import get_list_input @@ -15,6 +16,7 @@ import contact.ui.dialog from contact.ui.nav_utils import move_main_highlight, draw_main_arrows, get_msg_window_lines, wrap_text from contact.utilities.singleton import ui_state, interface_state, menu_state + MIN_COL = 1 # "effectively zero" without breaking curses root_win = None # set in main_ui @@ -832,14 +834,14 @@ def draw_packetlog_win() -> None: else get_name_from_database(packet["to"], "short").ljust(columns[1]) ) if "decoded" in packet: - port = packet["decoded"]["portnum"].ljust(columns[2]) - payload = (packet["decoded"]["payload"]).ljust(columns[3]) + port = str(packet["decoded"].get("portnum", "")).ljust(columns[2]) + parsed_payload = parse_protobuf(packet) else: port = "NO KEY".ljust(columns[2]) - payload = "NO KEY".ljust(columns[3]) + parsed_payload = "NO KEY" # Combine and truncate if necessary - logString = f"{from_id} {to_id} {port} {payload}" + logString = f"{from_id} {to_id} {port} {parsed_payload}" logString = logString[: width - 3] # Add to the window diff --git a/contact/utilities/utils.py b/contact/utilities/utils.py index 165b984..554a299 100644 --- a/contact/utilities/utils.py +++ b/contact/utilities/utils.py @@ -1,8 +1,11 @@ import datetime import time -from meshtastic.protobuf import config_pb2 -import contact.ui.default_config as config +from typing import Optional, Union +from google.protobuf.message import DecodeError +from meshtastic import protocols +from meshtastic.protobuf import config_pb2, mesh_pb2, portnums_pb2 +import contact.ui.default_config as config from contact.utilities.singleton import ui_state, interface_state @@ -136,6 +139,7 @@ def get_time_ago(timestamp): return f"{value} {unit} ago" return "now" + def add_new_message(channel_id, prefix, message): if channel_id not in ui_state.all_messages: ui_state.all_messages[channel_id] = [] @@ -162,4 +166,29 @@ def add_new_message(channel_id, prefix, message): ui_state.all_messages[channel_id].append((f"-- {current_hour} --", "")) # Add the message - ui_state.all_messages[channel_id].append((prefix,message)) + ui_state.all_messages[channel_id].append((prefix, message)) + + +def parse_protobuf(packet: dict) -> Union[str, dict]: + """Attempt to parse a decoded payload using the registered protobuf handler.""" + try: + decoded = packet.get("decoded") or {} + portnum = decoded.get("portnum") + payload = decoded.get("payload") + + if isinstance(payload, str): + return payload + + handler = protocols.get(portnums_pb2.PortNum.Value(portnum)) if portnum is not None else None + if handler is not None and handler.protobufFactory is not None: + try: + pb = handler.protobufFactory() + pb.ParseFromString(bytes(payload)) + return str(pb).replace("\n", " ").replace("\r", " ").strip() + except DecodeError: + return payload + + return payload + + except Exception: + return payload