First Attempt

Try merge. Will need testing and tweaking.
This commit is contained in:
madeofstown
2025-03-07 19:40:46 -08:00
committed by GitHub
6 changed files with 49 additions and 29 deletions
+15
View File
@@ -5,9 +5,12 @@ from meshview import mqtt_reader
from meshview import database
from meshview import mqtt_store
from meshview import web
from meshview import http
from meshview import models
import json
async def load_database_from_mqtt(mqtt_server: str , mqtt_port: int, topic: list, mqtt_user: str | None = None, mqtt_passwd: str | None = None):
async for topic, env in mqtt_reader.get_topic_envelopes(mqtt_server, mqtt_port, topic, mqtt_user, mqtt_passwd):
await mqtt_store.process_envelope(topic, env)
@@ -24,6 +27,17 @@ async def main(config):
if config["mqtt"]["password"] != "":
mqtt_passwd: str = config["mqtt"]["password"]
mqtt_topics = json.loads(config["mqtt"]["topics"])
# Create database with site configuration
async with database.async_session() as session:
site_config = models.SiteConfig(
site_domain = config["site"]["domain"],
site_title = config["site"]["title"],
site_message = config["site"]["message"]
)
session.add(site_config)
# print("Site configuration loaded to database")
async with asyncio.TaskGroup() as tg:
tg.create_task(
@@ -44,6 +58,7 @@ def load_config(file_path):
return config
if __name__ == '__main__':
parser = argparse.ArgumentParser("meshview")
parser.add_argument("--config", help="Path to the configuration file.", default="config.ini")
+7
View File
@@ -68,3 +68,10 @@ class Traceroute(Base):
done: Mapped[bool] = mapped_column(nullable=True)
route: Mapped[bytes] = mapped_column(nullable=True)
import_time: Mapped[datetime] = mapped_column(nullable=True)
class SiteConfig(Base):
__tablename__="site_config"
id: Mapped[int] = mapped_column(primary_key=True)
site_domain: Mapped[str] = mapped_column(nullable=False)
site_title: Mapped[str] = mapped_column(nullable=False)
site_message: Mapped[str] = mapped_column(nullable=True)
+9 -2
View File
@@ -2,9 +2,10 @@ import datetime
from sqlalchemy import select, func
from sqlalchemy.orm import lazyload
from meshview import database
from meshview.models import Packet, PacketSeen, Node, Traceroute
from meshview.models import Packet, PacketSeen, Node, Traceroute, SiteConfig
from sqlalchemy import text
async def get_node(node_id):
async with database.async_session() as session:
result = await session.execute(select(Node).where(Node.node_id == node_id))
@@ -313,4 +314,10 @@ async def get_nodes(role=None, channel=None, hw_model=None):
return [] # Return an empty list in case of failure
async def get_site_config():
async with database.async_session() as session:
query = select(SiteConfig)
result = await session.execute(query)
site_config = result.scalars().all()[-1]
return site_config
+2 -1
View File
@@ -35,7 +35,8 @@
</style>
</head>
<body hx-indicator="#spinner">
<br><div style="text-align:center"><strong>Bay Area Mesh - http://bayme.sh</strong></div>
<br><div style="text-align:center"><strong>{{ site_config.site_title }} - {{ site_config.site_domain }}</strong></div>
<div style="text-align: center;">{{ site_config.site_message }}</div>
<div style="text-align:center">Quick Links:&nbsp;&nbsp;<a href="/nodelist">Nodes</a>&nbsp;-&nbsp;<a href="/chat">Conversations</a>&nbsp;-&nbsp;<a href="/firehose">See <strong>everything</strong> </a>
&nbsp;-&nbsp;Mesh Graph <a href="/nodegraph/LongFast">LF</a>&nbsp;-&nbsp;<a href="/nodegraph/MediumSlow">MS </a>&nbsp;-&nbsp;<a href="/stats">Stats </a>
&nbsp;-&nbsp;<a href="/net">Weekly Net</a>&nbsp;-&nbsp;<a href="/map">Map</a>&nbsp;-&nbsp;<a href="/top">Top Traffic</a></div><br>
+1 -2
View File
@@ -3,11 +3,10 @@
{% block body %}
<div class="container">
<div class="row">
<div class="col-6">
<div>
{% include 'packet.html' %}
</div>
<div
class="col-6 sticky-top"
id="packet_details"
hx-get="/packet_details/{{packet.id}}"
hx-trigger="load"
+15 -24
View File
@@ -32,7 +32,6 @@ with open(os.path.join(os.path.dirname(__file__), '1x1.png'), 'rb') as png:
empty_png = png.read()
@dataclass
class Packet:
id: int
@@ -109,23 +108,6 @@ class UplinkedNode:
rssi: float
def generate_responce(request, body, raw_node_id="", node=None):
if "HX-Request" in request.headers:
return web.Response(text=body, content_type="text/html")
template = env.get_template("index.html")
return web.Response(
text=template.render(
is_hx_request="HX-Request" in request.headers,
raw_node_id=raw_node_id,
node_html=Markup(body),
node=node,
),
content_type="text/html",
)
async def build_trace(node_id):
trace = []
for raw_p in await store.get_packets_from(node_id, PortNum.POSITION_APP, since=datetime.timedelta(hours=24)):
@@ -209,6 +191,7 @@ def generate_response(request, body, raw_node_id="", node=None):
raw_node_id=raw_node_id,
node_html=Markup(body),
node=node,
site_config = await store.get_site_config(),
),
content_type="text/html",
)
@@ -268,6 +251,8 @@ async def node_match(request):
return web.Response(
text=template.render(
node_options=node_options,
site_config = await store.get_site_config()
),
content_type="text/html",
)
@@ -281,6 +266,7 @@ async def packet_list(request):
else:
portnum = None
async with asyncio.TaskGroup() as tg:
node = tg.create_task(store.get_node(node_id))
raw_packets = tg.create_task(store.get_packets(node_id,portnum, limit=200))
@@ -301,6 +287,7 @@ async def packet_list(request):
neighbors=neighbors,
has_telemetry=await has_telemetry,
query_string=request.query_string,
site_config = await store.get_site_config(),
),
content_type="text/html",
)
@@ -356,6 +343,7 @@ async def packet_details(request):
from_node_cord=from_node_cord,
uplinked_nodes=uplinked_nodes,
node=node,
site_config = await store.get_site_config(),
),
content_type="text/html",
)
@@ -373,10 +361,12 @@ async def packet_details(request):
text=template.render(
packets=(Packet.from_model(p) for p in packets),
portnum=portnum,
site_config = await store.get_site_config(),
),
content_type="text/html",
)
@routes.get("/packet/{packet_id}")
async def packet(request):
packet = await store.get_packet(int(request.match_info["packet_id"]))
@@ -388,7 +378,7 @@ async def packet(request):
template = env.get_template("packet_index.html")
return web.Response(
text=template.render(packet=Packet.from_model(packet), node=node),
text=template.render(packet=Packet.from_model(packet), site_config = await store.get_site_config()),
content_type="text/html",
)
@@ -1086,7 +1076,7 @@ async def nodelist(request):
template = env.get_template("nodelist.html")
print_memory_usage()
return web.Response(
text=template.render(nodes=nodes),
text=template.render(nodes=nodes, site_config = await store.get_site_config()),
content_type="text/html",
)
except Exception as e:
@@ -1122,7 +1112,7 @@ async def net(request):
# Render template
template = env.get_template("net.html")
return web.Response(
text=template.render(packets=filtered_packets),
text=template.render(packets=filtered_packets, site_config = await store.get_site_config()),
content_type="text/html",
)
@@ -1145,7 +1135,7 @@ async def map(request):
template = env.get_template("map.html")
print_memory_usage()
return web.Response(
text=template.render(nodes=nodes),
text=template.render(nodes=nodes, site_config = await store.get_site_config()),
content_type="text/html",
)
except Exception as e:
@@ -1179,6 +1169,7 @@ async def stats(request):
total_packets_seen=total_packets_seen,
total_nodes_longfast=total_nodes_longfast,
total_nodes_mediumslow=total_nodes_mediumslow,
site_config = await store.get_site_config(),
),
content_type="text/html",
)
@@ -1204,7 +1195,7 @@ async def top(request):
# Otherwise, fetch top traffic nodes as usual
top_nodes = await store.get_top_traffic_nodes()
template = env.get_template("top.html")
html_content = template.render(nodes=top_nodes)
html_content = template.render(nodes=top_nodes, site_config = await store.get_site_config())
return web.Response(
text=html_content,
@@ -1242,7 +1233,7 @@ async def chat(request):
#print("Rendering template...")
template = env.get_template("chat.html")
return web.Response(
text=template.render(packets=filtered_packets),
text=template.render(packets=filtered_packets, site_config = await store.get_site_config()),
content_type="text/html",
)