From 604fc5c2844702c45a97ec67c7dd0bbc3800a8c0 Mon Sep 17 00:00:00 2001 From: Pablo Revilla Date: Fri, 31 Jan 2025 14:19:28 -0800 Subject: [PATCH] Multile changes to the code. Important to mentioned that we added another column to the nodes table to report on last_update This can give us when the node was last seen on the mesh and provide some understanding if it is active. --- meshview/database.py | 13 ++++------- meshview/models.py | 2 +- meshview/store.py | 38 ++++++++------------------------ meshview/templates/firehose.html | 2 +- meshview/templates/node.html | 2 +- meshview/templates/stats.html | 2 +- meshview/web.py | 17 ++++++++------ 7 files changed, 27 insertions(+), 49 deletions(-) diff --git a/meshview/database.py b/meshview/database.py index 1d027ee..5451274 100644 --- a/meshview/database.py +++ b/meshview/database.py @@ -1,20 +1,15 @@ -from sqlalchemy.ext.asyncio import async_sessionmaker -from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy.ext.asyncio import create_async_engine - from meshview import models +from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker - -def init_database(database_connetion_string): +def init_database(database_connection_string): global engine, async_session kwargs = {} - if not database_connetion_string.startswith('sqlite'): + if not database_connection_string.startswith('sqlite'): kwargs['pool_size'] = 20 kwargs['max_overflow'] = 50 - engine = create_async_engine(database_connetion_string, echo=False, **kwargs) + engine = create_async_engine(database_connection_string, echo=False, **kwargs) async_session = async_sessionmaker(engine, expire_on_commit=False) - async def create_tables(): async with engine.begin() as conn: await conn.run_sync(models.Base.metadata.create_all) diff --git a/meshview/models.py b/meshview/models.py index 8932032..c1c5b2a 100644 --- a/meshview/models.py +++ b/meshview/models.py @@ -21,7 +21,7 @@ class Node(Base): last_lat: Mapped[int] = mapped_column(BigInteger, nullable=True) last_long: Mapped[int] = mapped_column(BigInteger, nullable=True) channel: Mapped[str] - + last_update: Mapped[datetime] class Packet(Base): __tablename__ = "packet" diff --git a/meshview/store.py b/meshview/store.py index 97c13d2..c7e3a9b 100644 --- a/meshview/store.py +++ b/meshview/store.py @@ -88,6 +88,7 @@ async def process_envelope(topic, env): node.short_name = user.short_name node.hw_model = hw_model node.role = role + node.last_update =datetime.datetime.now() # if need to update time of last update it may be here else: @@ -415,6 +416,7 @@ async def get_total_packet_count(): async def get_total_node_count(): async with database.async_session() as session: q = select(func.count(Node.id)) # Use SQLAlchemy's func to count nodes + q = q.where(Node.last_update > datetime.datetime.now() - datetime.timedelta(days=1)) # Look for nodes with nodeinfo updates in the last 24 hours result = await session.execute(q) return result.scalar() # Return the total count of nodes @@ -427,24 +429,13 @@ async def get_total_packet_seen_count(): async def get_total_node_count_longfast() -> int: - """ - Retrieves the total count of nodes where the channel is equal to 'LongFast'. - - This function queries the database asynchronously to count the number of nodes - in the `Node` table that meet the condition `channel == 'LongFast'`. It uses - SQLAlchemy's asynchronous session management and query construction. - - Returns: - int: The total count of nodes with `channel == 'LongFast'`. - - Raises: - Exception: If an error occurs during the database query execution. - """ try: # Open an asynchronous session with the database async with database.async_session() as session: # Build the query to count nodes where channel == 'LongFast' - q = select(func.count(Node.id)).filter(Node.channel == 'LongFast') + q = select(func.count(Node.id)) + q = q.where(Node.last_update > datetime.datetime.now() - datetime.timedelta( days=1)) # Look for nodes with nodeinfo updates in the last 24 hours + q = q.where(Node.channel == 'LongFast') # # Execute the query asynchronously and fetch the result result = await session.execute(q) @@ -458,25 +449,14 @@ async def get_total_node_count_longfast() -> int: async def get_total_node_count_mediumslow() -> int: - """ - Retrieves the total count of nodes where the channel is equal to 'MediumSlow'. - - This function queries the database asynchronously to count the number of nodes - in the `Node` table that meet the condition `channel == 'MediumSlow'`. It uses - SQLAlchemy's asynchronous session management and query construction. - - Returns: - int: The total count of nodes with `channel == 'MediumSlow'`. - - Raises: - Exception: If an error occurs during the database query execution. - """ try: # Open an asynchronous session with the database async with database.async_session() as session: # Build the query to count nodes where channel == 'LongFast' - q = select(func.count(Node.id)).filter(Node.channel == 'MediumSlow') - + q = select(func.count(Node.id)) + q = q.where(Node.last_update > datetime.datetime.now() - datetime.timedelta( + days=1)) # Look for nodes with nodeinfo updates in the last 24 hours + q = q.where(Node.channel == 'MediumSlow') # # Execute the query asynchronously and fetch the result result = await session.execute(q) diff --git a/meshview/templates/firehose.html b/meshview/templates/firehose.html index c5e36b8..c8da75b 100644 --- a/meshview/templates/firehose.html +++ b/meshview/templates/firehose.html @@ -23,7 +23,7 @@ >{{ name }} {% endfor %} - +
diff --git a/meshview/templates/node.html b/meshview/templates/node.html index 88f7da6..2bf8c57 100644 --- a/meshview/templates/node.html +++ b/meshview/templates/node.html @@ -61,7 +61,7 @@
- {% include "buttons.html" %} +
diff --git a/meshview/templates/stats.html b/meshview/templates/stats.html index 3fc73d1..0770699 100644 --- a/meshview/templates/stats.html +++ b/meshview/templates/stats.html @@ -16,7 +16,7 @@

- Total Nodes: + Total Nodes (Last 24 hours): {{ total_nodes }}

diff --git a/meshview/web.py b/meshview/web.py index 0c19810..bc8f06c 100644 --- a/meshview/web.py +++ b/meshview/web.py @@ -304,7 +304,6 @@ async def _packet_list(request, raw_packets, packet_event): content_type="text/html", ) - @routes.get("/chat_events") async def chat_events(request): chat_packet = env.get_template("chat_packet.html") @@ -408,7 +407,7 @@ class UplinkedNode: snr: float rssi: float - +# Updated code p.r. @routes.get("/packet_details/{packet_id}") async def packet_details(request): packet_id = int(request.match_info["packet_id"]) @@ -416,8 +415,11 @@ async def packet_details(request): packet = await store.get_packet(packet_id) from_node_cord = None - if packet.from_node and packet.from_node.last_lat: - from_node_cord = [packet.from_node.last_lat * 1e-7 , packet.from_node.last_long * 1e-7] + if packet and packet.from_node and packet.from_node.last_lat: + from_node_cord = [ + packet.from_node.last_lat * 1e-7, + packet.from_node.last_long * 1e-7, + ] uplinked_nodes = [] for p in packets_seen: @@ -444,6 +446,7 @@ async def packet_details(request): elif uplinked_nodes: map_center = [uplinked_nodes[0].lat, uplinked_nodes[0].long] + # Render the template and return the response template = env.get_template("packet_details.html") return web.Response( text=template.render( @@ -461,7 +464,7 @@ async def packet_details(request): portnum = request.query.get("portnum") if portnum: portnum = int(portnum) - packets = await store.get_packets(portnum=portnum) + packets = await store.get_packets(portnum=portnum, limit=50) template = env.get_template("firehose.html") return web.Response( text=template.render( @@ -726,7 +729,7 @@ async def graph_power_metrics(request): @routes.get("/graph/neighbors/{node_id}") async def graph_neighbors(request): - oldest = datetime.datetime.utcnow() - datetime.timedelta(days=4) + oldest = datetime.datetime.now() - datetime.timedelta(days=4) data = {} dates =[] @@ -774,7 +777,7 @@ async def graph_neighbors(request): @routes.get("/graph/neighbors2/{node_id}") async def graph_neighbors2(request): - oldest = datetime.datetime.utcnow() - datetime.timedelta(days=30) + oldest = datetime.datetime.now() - datetime.timedelta(days=30) data = [] node_ids = set()