From 9bfddb954de27dd1b480b8daa8d5058ce1a8c106 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Thu, 23 Jan 2025 12:08:14 -0800 Subject: [PATCH 1/4] init --- db_handler.py | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/db_handler.py b/db_handler.py index cde4edd..57806da 100644 --- a/db_handler.py +++ b/db_handler.py @@ -1,6 +1,8 @@ import sqlite3 import globals import time +from datetime import datetime + from utilities.utils import get_name_from_number def get_table_name(channel): @@ -69,6 +71,8 @@ def update_ack_nak(channel, timestamp, message, ack): print(f"Unexpected error in update_ack_nak: {e}") +from datetime import datetime + def load_messages_from_db(): """Load messages from the database for all channels and update globals.all_messages and globals.channel_list.""" try: @@ -82,18 +86,18 @@ def load_messages_from_db(): # Iterate through each table and fetch its messages for table_name in tables: - quoted_table_name = f'"{table_name}"' # Quote the table name becuase we begin with numerics and contain spaces + quoted_table_name = f'"{table_name}"' # Quote the table name because we begin with numerics and contain spaces table_columns = [i[1] for i in db_cursor.execute(f'PRAGMA table_info({quoted_table_name})')] - if("ack_type" not in table_columns): + if "ack_type" not in table_columns: update_table_query = f"ALTER TABLE {quoted_table_name} ADD COLUMN ack_type TEXT" db_cursor.execute(update_table_query) - query = f'SELECT user_id, message_text, ack_type FROM {quoted_table_name}' + query = f'SELECT user_id, message_text, timestamp, ack_type FROM {quoted_table_name}' try: # Fetch all messages from the table db_cursor.execute(query) - db_messages = [(row[0], row[1], row[2]) for row in db_cursor.fetchall()] # Save as tuples + db_messages = [(row[0], row[1], row[2], row[3]) for row in db_cursor.fetchall()] # Save as tuples # Extract the channel name from the table name channel = table_name.split("_")[1] @@ -109,22 +113,32 @@ def load_messages_from_db(): if channel not in globals.all_messages: globals.all_messages[channel] = [] - # Add messages to globals.all_messages in tuple format - for user_id, message, ack_type in db_messages: - if user_id == str(globals.myNodeNum): - ack_str = globals.ack_unknown_str - if(ack_type == "Implicit"): - ack_str = globals.ack_implicit_str - elif(ack_type == "Ack"): - ack_str = globals.ack_str - elif(ack_type == "Nak"): - ack_str = globals.nak_str + # Add messages to globals.all_messages grouped by hourly timestamp + hourly_messages = {} + for user_id, message, timestamp, ack_type in db_messages: + hour = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:00:00') + if hour not in hourly_messages: + hourly_messages[hour] = [] + + ack_str = globals.ack_unknown_str + if ack_type == "Implicit": + ack_str = globals.ack_implicit_str + elif ack_type == "Ack": + ack_str = globals.ack_str + elif ack_type == "Nak": + ack_str = globals.nak_str + if user_id == str(globals.myNodeNum): formatted_message = (f"{globals.sent_message_prefix}{ack_str}: ", message) - else: + else: formatted_message = (f"{globals.message_prefix} {get_name_from_number(int(user_id), 'short')}: ", message) - - globals.all_messages[channel].append(formatted_message) + + hourly_messages[hour].append(formatted_message) + + # Flatten the hourly messages into globals.all_messages[channel] + for hour, messages in sorted(hourly_messages.items()): + globals.all_messages[channel].append((f"--- {hour} ---", "")) + globals.all_messages[channel].extend(messages) except sqlite3.Error as e: print(f"SQLite error while loading messages from table '{table_name}': {e}") From 7fcc9abd7686ca7f6dc6043ecfa246634becd9eb Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Thu, 23 Jan 2025 12:16:59 -0800 Subject: [PATCH 2/4] formatting --- db_handler.py | 2 +- ui/curses_ui.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db_handler.py b/db_handler.py index 57806da..6eab974 100644 --- a/db_handler.py +++ b/db_handler.py @@ -137,7 +137,7 @@ def load_messages_from_db(): # Flatten the hourly messages into globals.all_messages[channel] for hour, messages in sorted(hourly_messages.items()): - globals.all_messages[channel].append((f"--- {hour} ---", "")) + globals.all_messages[channel].append((f"-- {hour} --", "")) globals.all_messages[channel].extend(messages) except sqlite3.Error as e: diff --git a/ui/curses_ui.py b/ui/curses_ui.py index db8ba50..f3acf71 100644 --- a/ui/curses_ui.py +++ b/ui/curses_ui.py @@ -100,7 +100,7 @@ def draw_messages_window(scroll_to_bottom = False): messages_pad.resize(msg_line_count, messages_box.getmaxyx()[1]) for line in wrapped_lines: - color = curses.color_pair(3) if prefix.startswith(globals.sent_message_prefix) else curses.color_pair(2) + color = curses.color_pair(4) if prefix.startswith("--") else (curses.color_pair(3) if prefix.startswith(globals.sent_message_prefix) else curses.color_pair(2)) messages_pad.addstr(row, 1, line, color) row += 1 From 1b2701e1a133ffa345ea220da162e6ec16ba7410 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Thu, 23 Jan 2025 12:20:57 -0800 Subject: [PATCH 3/4] white stamps and no seconds --- db_handler.py | 2 +- ui/curses_ui.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db_handler.py b/db_handler.py index 6eab974..061ab07 100644 --- a/db_handler.py +++ b/db_handler.py @@ -116,7 +116,7 @@ def load_messages_from_db(): # Add messages to globals.all_messages grouped by hourly timestamp hourly_messages = {} for user_id, message, timestamp, ack_type in db_messages: - hour = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:00:00') + hour = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:00') if hour not in hourly_messages: hourly_messages[hour] = [] diff --git a/ui/curses_ui.py b/ui/curses_ui.py index f3acf71..fbb11b6 100644 --- a/ui/curses_ui.py +++ b/ui/curses_ui.py @@ -100,7 +100,7 @@ def draw_messages_window(scroll_to_bottom = False): messages_pad.resize(msg_line_count, messages_box.getmaxyx()[1]) for line in wrapped_lines: - color = curses.color_pair(4) if prefix.startswith("--") else (curses.color_pair(3) if prefix.startswith(globals.sent_message_prefix) else curses.color_pair(2)) + color = curses.color_pair(1) if prefix.startswith("--") else (curses.color_pair(3) if prefix.startswith(globals.sent_message_prefix) else curses.color_pair(2)) messages_pad.addstr(row, 1, line, color) row += 1 From 07f0721fd51ec40b290030faf05789102bf61256 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Thu, 23 Jan 2025 15:19:45 -0800 Subject: [PATCH 4/4] add hourly timestamp to rx and tx messages --- message_handlers/rx_handler.py | 40 ++++++++++++++++++++++++++-------- message_handlers/tx_handler.py | 30 +++++++++++++++++++++---- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/message_handlers/rx_handler.py b/message_handlers/rx_handler.py index 6eabe17..cff5842 100644 --- a/message_handlers/rx_handler.py +++ b/message_handlers/rx_handler.py @@ -5,13 +5,15 @@ from ui.curses_ui import draw_packetlog_win, draw_node_list, draw_messages_windo from db_handler import save_message_to_db, maybe_store_nodeinfo_in_db +from datetime import datetime + def on_receive(packet, interface): global nodes_win - # update packet log + # Update packet log globals.packet_buffer.append(packet) if len(globals.packet_buffer) > 20: - # trim buffer to 20 packets + # Trim buffer to 20 packets globals.packet_buffer = globals.packet_buffer[-20:] if globals.display_log: @@ -20,10 +22,9 @@ def on_receive(packet, interface): if 'decoded' not in packet: return - # Assume any incoming packet could update the last seen time for a node, so we - # may need to reorder the list. This could probably be limited to specific packets. + # Assume any incoming packet could update the last seen time for a node new_node_list = get_node_list() - if(new_node_list != globals.node_list): + if new_node_list != globals.node_list: globals.node_list = new_node_list draw_node_list() @@ -42,6 +43,7 @@ def on_receive(packet, interface): channel_number = packet['channel'] else: channel_number = 0 + if packet['to'] == globals.myNodeNum: if packet['from'] in globals.channel_list: pass @@ -65,15 +67,35 @@ def on_receive(packet, interface): if globals.channel_list[channel_number] not in globals.all_messages: globals.all_messages[globals.channel_list[channel_number]] = [] + # Timestamp handling + current_timestamp = int(packet['rxTime']) # Use the packet's rxTime for timestamp + current_hour = datetime.fromtimestamp(current_timestamp).strftime('%Y-%m-%d %H:00') + + # Retrieve the last timestamp if available + channel_messages = globals.all_messages[globals.channel_list[channel_number]] + if channel_messages: + # Check the last entry for a timestamp + for entry in reversed(channel_messages): + if entry[0].startswith("--"): + last_hour = entry[0].strip("- ").strip() + break + else: + last_hour = None + else: + last_hour = None + + # Add a new timestamp if it's a new hour + if last_hour != current_hour: + globals.all_messages[globals.channel_list[channel_number]].append((f"-- {current_hour} --", "")) + globals.all_messages[globals.channel_list[channel_number]].append((f"{globals.message_prefix} {message_from_string} ", message_string)) - if(refresh_channels): + if refresh_channels: draw_channel_list() - if(refresh_messages): + if refresh_messages: draw_messages_window(True) save_message_to_db(globals.channel_list[channel_number], message_from_id, message_string) except KeyError as e: - print(f"Error processing packet: {e}") - + print(f"Error processing packet: {e}") \ No newline at end of file diff --git a/message_handlers/tx_handler.py b/message_handlers/tx_handler.py index 5b697dd..0f4f726 100644 --- a/message_handlers/tx_handler.py +++ b/message_handlers/tx_handler.py @@ -1,3 +1,4 @@ +from datetime import datetime from meshtastic import BROADCAST_NUM from db_handler import save_message_to_db, update_ack_nak from meshtastic.protobuf import mesh_pb2, portnums_pb2 @@ -106,14 +107,14 @@ def on_response_traceroute(packet): globals.all_messages[globals.channel_list[channel_number]] = [] globals.all_messages[globals.channel_list[channel_number]].append((f"{globals.message_prefix} {message_from_string}", msg_str)) - if(refresh_channels): + if refresh_channels: draw_channel_list() - if(refresh_messages): + if refresh_messages: draw_messages_window(True) save_message_to_db(globals.channel_list[channel_number], packet['from'], msg_str) -def send_message(message, destination=BROADCAST_NUM, channel=0): +def send_message(message, destination=BROADCAST_NUM, channel=0): myid = globals.myNodeNum send_on_channel = 0 channel_id = globals.channel_list[channel] @@ -136,11 +137,32 @@ def send_message(message, destination=BROADCAST_NUM, channel=0): if channel_id not in globals.all_messages: globals.all_messages[channel_id] = [] + # Handle timestamp logic + current_timestamp = int(datetime.now().timestamp()) # Get current timestamp + current_hour = datetime.fromtimestamp(current_timestamp).strftime('%Y-%m-%d %H:00') + + # Retrieve the last timestamp if available + channel_messages = globals.all_messages[channel_id] + if channel_messages: + # Check the last entry for a timestamp + for entry in reversed(channel_messages): + if entry[0].startswith("--"): + last_hour = entry[0].strip("- ").strip() + break + else: + last_hour = None + else: + last_hour = None + + # Add a new timestamp if it's a new hour + if last_hour != current_hour: + globals.all_messages[channel_id].append((f"-- {current_hour} --", "")) + globals.all_messages[channel_id].append((globals.sent_message_prefix + globals.ack_unknown_str + ": ", message)) timestamp = save_message_to_db(channel_id, myid, message) - ack_naks[sent_message_data.id] = {'channel' : channel_id, 'messageIndex' : len(globals.all_messages[channel_id]) - 1, 'timestamp' : timestamp } + ack_naks[sent_message_data.id] = {'channel': channel_id, 'messageIndex': len(globals.all_messages[channel_id]) - 1, 'timestamp': timestamp} def send_traceroute(): r = mesh_pb2.RouteDiscovery()