mirror of
https://github.com/pablorevilla-meshtastic/meshview.git
synced 2026-08-08 01:42:44 +02:00
First Attempt
Try merge. Will need testing and tweaking.
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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: <a href="/nodelist">Nodes</a> - <a href="/chat">Conversations</a> - <a href="/firehose">See <strong>everything</strong> </a>
|
||||
- Mesh Graph <a href="/nodegraph/LongFast">LF</a> - <a href="/nodegraph/MediumSlow">MS </a> - <a href="/stats">Stats </a>
|
||||
- <a href="/net">Weekly Net</a> - <a href="/map">Map</a> - <a href="/top">Top Traffic</a></div><br>
|
||||
|
||||
@@ -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
@@ -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",
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user