diff --git a/db_utils.py b/db_utils.py index 98574f1..9ebfa97 100644 --- a/db_utils.py +++ b/db_utils.py @@ -1,3 +1,4 @@ +import json import sqlite3 @@ -8,9 +9,48 @@ def initialize_database(): cursor.execute( "CREATE TABLE IF NOT EXISTS longnames (meshtastic_id TEXT PRIMARY KEY, longname TEXT)" ) + cursor.execute( + "CREATE TABLE IF NOT EXISTS plugin_data (plugin_name TEXT, meshtastic_id TEXT, data TEXT, PRIMARY KEY (plugin_name, meshtastic_id))" + ) conn.commit() +def store_plugin_data(plugin_name, meshtastic_id, data): + with sqlite3.connect("meshtastic.sqlite") as conn: + cursor = conn.cursor() + cursor.execute( + "INSERT OR REPLACE INTO plugin_data (plugin_name, meshtastic_id, data) VALUES (?, ?, ?) ON CONFLICT (plugin_name, meshtastic_id) DO UPDATE SET data = ?", + (plugin_name, meshtastic_id, json.dumps(data), json.dumps(data)), + ) + conn.commit() + + +# Get the data for a given plugin and Meshtastic ID +def get_plugin_data_for_node(plugin_name, meshtastic_id): + with sqlite3.connect("meshtastic.sqlite") as conn: + cursor = conn.cursor() + cursor.execute( + "SELECT data FROM plugin_data WHERE plugin_name=? AND meshtastic_id=?", + ( + plugin_name, + meshtastic_id, + ), + ) + result = cursor.fetchone() + return json.loads(result[0] if result else "[]") + + +# Get the data for a given plugin +def get_plugin_data(plugin_name): + with sqlite3.connect("meshtastic.sqlite") as conn: + cursor = conn.cursor() + cursor.execute( + "SELECT data FROM plugin_data WHERE plugin_name=? ", + (plugin_name,), + ) + return cursor.fetchall() + + # Get the longname for a given Meshtastic ID def get_longname(meshtastic_id): with sqlite3.connect("meshtastic.sqlite") as conn: diff --git a/main.py b/main.py index 099d51d..25127e6 100644 --- a/main.py +++ b/main.py @@ -70,11 +70,11 @@ async def main(): # Update longnames update_longnames(meshtastic_interface.nodes) - matrix_logger.info("Syncing with Matrix server...") + matrix_logger.info("Syncing with server...") await matrix_client.sync_forever(timeout=30000) matrix_logger.info("Sync completed.") except Exception as e: - matrix_logger.error(f"Error syncing with Matrix server: {e}") + matrix_logger.error(f"Error syncing with server: {e}") await asyncio.sleep(60) # Update longnames every 60 seconds diff --git a/meshtastic_utils.py b/meshtastic_utils.py index 806a299..f785927 100644 --- a/meshtastic_utils.py +++ b/meshtastic_utils.py @@ -35,7 +35,7 @@ def connect_meshtastic(): # Callback for new messages from Meshtastic def on_meshtastic_message(packet, loop=None): - from matrix_utils import connect_matrix, matrix_relay + from matrix_utils import matrix_relay sender = packet["fromId"] @@ -98,4 +98,16 @@ def on_meshtastic_message(packet, loop=None): ) else: portnum = packet["decoded"]["portnum"] - logger.debug(f"Ignoring {portnum} packet") + + logger.debug(f"Detected {portnum} packet") + + plugins = load_plugins() + for plugin in plugins: + logger.debug(f"Running plugin {plugin.plugin_name}") + + asyncio.run_coroutine_threadsafe( + plugin.handle_meshtastic_message( + packet, formatted_message=None, longname=None, meshnet_name=None + ), + loop=loop, + ) diff --git a/plugins/base_plugin.py b/plugins/base_plugin.py index 1eaadba..f9787a5 100644 --- a/plugins/base_plugin.py +++ b/plugins/base_plugin.py @@ -1,10 +1,12 @@ from abc import ABC, abstractmethod from log_utils import get_logger from config import relay_config +from db_utils import store_plugin_data, get_plugin_data, get_plugin_data_for_node class BasePlugin(ABC): plugin_name = None + max_data_rows_per_node = 10 def __init__(self) -> None: super().__init__() @@ -13,6 +15,16 @@ def __init__(self) -> None: if "plugins" in relay_config and self.plugin_name in relay_config["plugins"]: self.config = relay_config["plugins"][self.plugin_name] + def store_node_data(self, meshtastic_id, data): + data = data[-self.max_data_rows_per_node :] + store_plugin_data(self.plugin_name, meshtastic_id, data) + + def get_node_data(self, meshtastic_id): + return get_plugin_data_for_node(self.plugin_name, meshtastic_id) + + def get_data(self): + return get_plugin_data(self.plugin_name) + @abstractmethod async def handle_meshtastic_message( packet, formatted_message, longname, meshnet_name