Website configuration in config.ini

This commit is contained in:
madeofstown
2025-03-08 19:24:17 -08:00
parent 95abb79af4
commit 83033a3a64
6 changed files with 34 additions and 74 deletions

View File

@@ -7,25 +7,9 @@ parser.add_argument("--config", type=str, default="config.ini", help="Path to co
args = parser.parse_args()
# Initialize config parser
config = configparser.ConfigParser()
if not config.read(args.config):
config_parser = configparser.ConfigParser()
if not config_parser.read(args.config):
raise FileNotFoundError(f"Config file '{args.config}' not found! Ensure the file exists.")
# MQTT settings
SERVER = config["MQTT"].get("SERVER", "localhost")
TOPICS = config["MQTT"].get("TOPICS", "").split(",") # Convert to list
MQTT_PORT = int(config["MQTT"].get("PORT", 1883))
USERNAME = config["MQTT"].get("USERNAME", "")
PASSWORD = config["MQTT"].get("PASSWORD", "")
CONFIG = {section: dict(config_parser.items(section)) for section in config_parser.sections()}
# Database settings
CONNECTION_STRING = config["DATABASE"].get("CONNECTION_STRING", "sqlite:///meshview.db")
# Server settings
BIND = config["SERVER"].get("BIND", "0.0.0.0")
WEB_PORT = int(config["SERVER"].get("PORT", 8080))
TLS_CERTS = config["SERVER"].get("TLS_CERTS", "")
ACME_CHALLENGE = config["SERVER"].get("ACME_CHALLENGE", "")
# Website settings
TITLE = config["WEBSITE"].get("TITLE", "MeshView")

View File

@@ -33,7 +33,7 @@ class Packet(Base):
)
to_node_id: Mapped[int] = mapped_column(BigInteger,nullable=True)
to_node: Mapped["Node"] = relationship(
primaryjoin="Packet.to_node_id == foreign(Node.node_id)", lazy="joined"
primaryjoin="Packet.to_node_id == foreign(Node.node_id)", lazy="joined", overlaps="from_node"
)
payload: Mapped[bytes] = mapped_column(nullable=True)
import_time: Mapped[datetime] = mapped_column(nullable=True)
@@ -45,7 +45,7 @@ class PacketSeen(Base):
packet_id = mapped_column(ForeignKey("packet.id"), primary_key=True)
node_id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
node: Mapped["Node"] = relationship(
lazy="joined", primaryjoin="PacketSeen.node_id == foreign(Node.node_id)"
lazy="joined", primaryjoin="PacketSeen.node_id == foreign(Node.node_id)", overlaps="from_node,to_node"
)
rx_time: Mapped[int] = mapped_column(BigInteger, primary_key=True)
hop_limit: Mapped[int] = mapped_column(nullable=True)
@@ -68,10 +68,3 @@ 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)

View File

@@ -2,7 +2,7 @@ import datetime
from sqlalchemy import select, func
from sqlalchemy.orm import lazyload
from meshview import database
from meshview.models import Packet, PacketSeen, Node, Traceroute, SiteConfig
from meshview.models import Packet, PacketSeen, Node, Traceroute
from sqlalchemy import text
@@ -312,12 +312,3 @@ async def get_nodes(role=None, channel=None, hw_model=None):
except Exception as e:
print("error reading DB") # Consider using logging instead of print
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)
#print(result.scalar())
site_config = result.scalars().all()[-1]
return site_config

View File

@@ -35,8 +35,8 @@
</style>
</head>
<body hx-indicator="#spinner">
<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>
<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>

View File

@@ -24,10 +24,13 @@ from meshview import database
import psutil
import gc
from meshview import config
import json
CONFIG = config.CONFIG
env = Environment(loader=PackageLoader("meshview"), autoescape=select_autoescape())
# Start Database
database.init_database(config.CONNECTION_STRING)
database.init_database(CONFIG["database"]["connection_string"])
# Optimize garbage collection frequency
gc.set_threshold(100, 10, 10)
@@ -254,7 +257,7 @@ async def node_match(request):
return web.Response(
text=template.render(
node_options=node_options,
site_config = await store.get_site_config()
site_config = CONFIG
),
content_type="text/html",
@@ -290,7 +293,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(),
site_config = CONFIG,
),
content_type="text/html",
)
@@ -346,7 +349,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(),
site_config = CONFIG,
),
content_type="text/html",
)
@@ -364,7 +367,7 @@ 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(),
site_config = CONFIG,
),
content_type="text/html",
)
@@ -381,7 +384,7 @@ async def packet(request):
template = env.get_template("packet_index.html")
return web.Response(
text=template.render(packet=Packet.from_model(packet), site_config = await store.get_site_config()),
text=template.render(packet=Packet.from_model(packet), site_config = CONFIG),
content_type="text/html",
)
@@ -1079,7 +1082,7 @@ async def nodelist(request):
template = env.get_template("nodelist.html")
print_memory_usage()
return web.Response(
text=template.render(nodes=nodes, site_config = await store.get_site_config()),
text=template.render(nodes=nodes, site_config = CONFIG),
content_type="text/html",
)
except Exception as e:
@@ -1115,7 +1118,7 @@ async def net(request):
# Render template
template = env.get_template("net.html")
return web.Response(
text=template.render(packets=filtered_packets, site_config = await store.get_site_config()),
text=template.render(packets=filtered_packets, site_config = CONFIG),
content_type="text/html",
)
@@ -1138,7 +1141,7 @@ async def map(request):
template = env.get_template("map.html")
print_memory_usage()
return web.Response(
text=template.render(nodes=nodes, site_config = await store.get_site_config()),
text=template.render(nodes=nodes, site_config = CONFIG),
content_type="text/html",
)
except Exception as e:
@@ -1172,7 +1175,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(),
site_config = CONFIG,
),
content_type="text/html",
)
@@ -1193,12 +1196,12 @@ async def top(request):
node_traffic = await store.get_node_traffic(int(node_id))
print(node_traffic)
template = env.get_template("node_traffic.html") # Render a different template
html_content = template.render(traffic=node_traffic, node_id=node_id, site_config = await store.get_site_config())
html_content = template.render(traffic=node_traffic, node_id=node_id, site_config = CONFIG)
else:
# 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, site_config = await store.get_site_config())
html_content = template.render(nodes=top_nodes, site_config = CONFIG)
return web.Response(
text=html_content,
@@ -1236,7 +1239,7 @@ async def chat(request):
#print("Rendering template...")
template = env.get_template("chat.html")
return web.Response(
text=template.render(packets=filtered_packets, site_config = await store.get_site_config()),
text=template.render(packets=filtered_packets, site_config = CONFIG),
content_type="text/html",
)
@@ -1326,7 +1329,7 @@ async def nodegraph(request):
text=template.render(
nodes=nodes_with_edges,
edges=edges, # Pass edges with color info
site_config = await store.get_site_config(),
site_config = CONFIG,
),
content_type="text/html",
)
@@ -1336,8 +1339,10 @@ async def nodegraph(request):
@routes.get("/config")
async def get_config(request):
return web.json_response({
"Server": config.SERVER,
"Title": config.TITLE
"Server": CONFIG["site"]["domain"],
"Title": CONFIG["site"]["title"],
"Message": CONFIG["site"]["message"],
"Topics": json.loads(CONFIG["mqtt"]["topics"])
})
@@ -1346,13 +1351,13 @@ async def run_server():
app.add_routes(routes)
runner = web.AppRunner(app)
await runner.setup()
if config.TLS_CERTS:
if CONFIG["server"]["tls_cert"]:
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_context.load_cert_chain(config.TLS_CERTS)
ssl_context.load_cert_chain(CONFIG["server"]["tls_cert"])
else:
ssl_context = None
for host in config.BIND:
site = web.TCPSite(runner, host, config.WEB_PORT, ssl_context=ssl_context)
for host in CONFIG["server"]["bind"]:
site = web.TCPSite(runner, host, CONFIG["server"]["port"], ssl_context=ssl_context)
await site.start()
while True:
await asyncio.sleep(3600) # sleep forever

View File

@@ -4,7 +4,6 @@ import configparser
from meshview import mqtt_reader
from meshview import mqtt_database
from meshview import mqtt_store
from meshview import models
import json
@@ -24,19 +23,7 @@ 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 mqtt_database.async_session() as session:
print(config["site"]["domain"])
site_config = models.SiteConfig(
site_domain = config["site"]["domain"],
site_title = config["site"]["title"],
site_message = config["site"]["message"]
)
session.add(site_config)
await session.commit()
# print("Site configuration loaded to database")
async with asyncio.TaskGroup() as tg:
tg.create_task(