diff --git a/db_handler.py b/db_handler.py index 5da7bb9..ef0255c 100644 --- a/db_handler.py +++ b/db_handler.py @@ -3,41 +3,70 @@ import globals import time from utilities.utils import get_nodeNum, get_name_from_number +def get_table_name(channel): + # Construct the table name + table_name = f"{str(get_nodeNum())}_{channel}_messages" + quoted_table_name = f'"{table_name}"' # Quote the table name becuase we begin with numerics and contain spaces + return quoted_table_name + def save_message_to_db(channel, user_id, message_text): """Save messages to the database, ensuring the table exists.""" try: with sqlite3.connect(globals.db_file_path) as db_connection: db_cursor = db_connection.cursor() - # Construct the table name - table_name = f"{str(get_nodeNum())}_{channel}_messages" - quoted_table_name = f'"{table_name}"' # Quote the table name becuase we begin with numerics and contain spaces + quoted_table_name = get_table_name(channel) # Ensure the table exists create_table_query = f''' CREATE TABLE IF NOT EXISTS {quoted_table_name} ( user_id TEXT, message_text TEXT, - timestamp INTEGER + timestamp INTEGER, + ack_type TEXT ) ''' + db_cursor.execute(create_table_query) + timestamp = int(time.time()) + # Insert the message insert_query = f''' - INSERT INTO {quoted_table_name} (user_id, message_text, timestamp) - VALUES (?, ?, ?) + INSERT INTO {quoted_table_name} (user_id, message_text, timestamp, ack_type) + VALUES (?, ?, ?, ?) ''' - db_cursor.execute(insert_query, (user_id, message_text, int(time.time()))) - + db_cursor.execute(insert_query, (user_id, message_text, timestamp, None)) db_connection.commit() + return timestamp + except sqlite3.Error as e: print(f"SQLite error in save_message_to_db: {e}") except Exception as e: print(f"Unexpected error in save_message_to_db: {e}") +def update_ack_nak(channel, timestamp, message, ack): + try: + with sqlite3.connect(globals.db_file_path) as db_connection: + db_cursor = db_connection.cursor() + update_query = f""" + UPDATE {get_table_name(channel)} + SET ack_type = '{ack}' + WHERE user_id = {str(get_nodeNum())} AND + timestamp = {timestamp} AND + message_text = '{message}' + """ + db_cursor.execute(update_query) + db_connection.commit() + + except sqlite3.Error as e: + print(f"SQLite error in update_ack_nak: {e}") + + except Exception as e: + print(f"Unexpected error in update_ack_nak: {e}") + def load_messages_from_db(): """Load messages from the database for all channels and update globals.all_messages and globals.channel_list.""" @@ -52,12 +81,18 @@ def load_messages_from_db(): # Iterate through each table and fetch its messages for table_name in tables: - query = f'SELECT user_id, message_text FROM "{table_name}"' + quoted_table_name = f'"{table_name}"' # Quote the table name becuase 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): + 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}' try: # Fetch all messages from the table db_cursor.execute(query) - db_messages = [(row[0], row[1]) for row in db_cursor.fetchall()] # Save as tuples + db_messages = [(row[0], row[1], row[2]) for row in db_cursor.fetchall()] # Save as tuples # Extract the channel name from the table name channel = table_name.split("_")[1] @@ -74,9 +109,17 @@ def load_messages_from_db(): globals.all_messages[channel] = [] # Add messages to globals.all_messages in tuple format - for user_id, message in db_messages: + for user_id, message, ack_type in db_messages: if user_id == str(get_nodeNum()): - formatted_message = (f"{globals.sent_message_prefix}: ", message) + 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 + + formatted_message = (f"{globals.sent_message_prefix}{ack_str}: ", message) else: formatted_message = (f"{globals.message_prefix} {get_name_from_number(int(user_id), 'short')}: ", message) @@ -224,6 +267,5 @@ def maybe_store_nodeinfo_in_db(packet): except sqlite3.Error as e: print(f"SQLite error in maybe_store_nodeinfo_in_db: {e}") - finally: db_connection.close() diff --git a/globals.py b/globals.py index c0ac1fe..9aec34d 100644 --- a/globals.py +++ b/globals.py @@ -16,5 +16,9 @@ interface = None display_log = False message_prefix = ">>" sent_message_prefix = message_prefix + " Sent" +ack_implicit_str = "[◌]" +ack_str = "[✓]" +nak_str = "[x]" +ack_unknown_str = "[…]" notification_symbol = "*" node_list = [] diff --git a/message_handlers/tx_handler.py b/message_handlers/tx_handler.py index 74f7300..58bca4d 100644 --- a/message_handlers/tx_handler.py +++ b/message_handlers/tx_handler.py @@ -1,5 +1,5 @@ from meshtastic import BROADCAST_NUM -from db_handler import save_message_to_db +from db_handler import save_message_to_db, update_ack_nak from utilities.utils import get_nodeNum import globals @@ -17,16 +17,22 @@ def onAckNak(packet): message = globals.all_messages[acknak['channel']][acknak['messageIndex']][1] confirm_string = " " + ack_type = None if(packet['decoded']['routing']['errorReason'] == "NONE"): if(packet['from'] == get_nodeNum()): # Ack "from" ourself means implicit ACK - confirm_string = "[◌]" + confirm_string = globals.ack_implicit_str + ack_type = "Implicit" else: - confirm_string = "[✓]" + confirm_string = globals.ack_str + ack_type = "Ack" else: - confirm_string = "[x]" + confirm_string = globals.nak_str + ack_type = "Nak" globals.all_messages[acknak['channel']][acknak['messageIndex']] = (globals.sent_message_prefix + confirm_string + ": ", message) + update_ack_nak(acknak['channel'], acknak['timestamp'], message, ack_type) + draw_messages_window() def send_message(message, destination=BROADCAST_NUM, channel=0): @@ -50,12 +56,12 @@ def send_message(message, destination=BROADCAST_NUM, channel=0): ) # Add sent message to the messages dictionary - if channel_id in globals.all_messages: - globals.all_messages[channel_id].append((globals.sent_message_prefix + "[…]: ", message)) - else: - globals.all_messages[channel_id] = [(globals.sent_message_prefix + "[…]: ", message)] + if channel_id not in globals.all_messages: + globals.all_messages[channel_id] = [] - ack_naks[sent_message_data.id] = {'channel' : channel_id, 'messageIndex' : len(globals.all_messages[channel_id]) - 1 } + 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 } - save_message_to_db(channel_id, myid, message)