mirror of
https://github.com/pablorevilla-meshtastic/meshview.git
synced 2026-03-04 23:27:46 +01:00
Changes:
- Added the link to another sample instance
This commit is contained in:
@@ -144,14 +144,6 @@ async def get_total_packet_count():
|
||||
result = await session.execute(q)
|
||||
return result.scalar() # Return the total count of packets
|
||||
|
||||
# We count the total amount of nodes
|
||||
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
|
||||
|
||||
# We count the total amount of seen packets
|
||||
async def get_total_packet_seen_count():
|
||||
async with database.async_session() as session:
|
||||
@@ -160,59 +152,24 @@ async def get_total_packet_seen_count():
|
||||
return result.scalar() # Return the total count of seen packets
|
||||
|
||||
|
||||
async def get_total_node_count_longfast() -> int:
|
||||
|
||||
async def get_total_node_count(channel: str = None) -> int:
|
||||
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))
|
||||
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') #
|
||||
q = select(func.count(Node.id)).where(
|
||||
Node.last_update > datetime.datetime.now() - datetime.timedelta(days=1)
|
||||
)
|
||||
|
||||
if channel:
|
||||
q = q.where(Node.channel == channel)
|
||||
|
||||
# Execute the query asynchronously and fetch the result
|
||||
result = await session.execute(q)
|
||||
|
||||
# Return the scalar value (the count of nodes)
|
||||
return result.scalar()
|
||||
except Exception as e:
|
||||
# Log or handle the exception if needed (optional, replace with logging if necessary)
|
||||
print(f"An error occurred: {e}")
|
||||
return 0 # Return 0 or an appropriate fallback value in case of an error
|
||||
return 0
|
||||
|
||||
|
||||
async def get_total_node_count_mediumslow() -> int:
|
||||
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))
|
||||
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)
|
||||
|
||||
# Return the scalar value (the count of nodes)
|
||||
return result.scalar()
|
||||
except Exception as e:
|
||||
# Log or handle the exception if needed (optional, replace with logging if necessary)
|
||||
print(f"An error occurred: {e}")
|
||||
return 0 # Return 0 or an appropriate fallback value in case of an error
|
||||
|
||||
|
||||
# Get Nodes for mediumslow only
|
||||
# p.r.
|
||||
async def get_nodes_mediumslow():
|
||||
async with database.async_session() as session:
|
||||
result = await session.execute(
|
||||
select(Node)
|
||||
.where(
|
||||
(Node.channel == "MediumSlow")
|
||||
)
|
||||
)
|
||||
|
||||
return result.scalars()
|
||||
|
||||
async def get_top_traffic_nodes():
|
||||
async with database.async_session() as session:
|
||||
result = await session.execute(text("""
|
||||
@@ -312,3 +269,4 @@ 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
|
||||
|
||||
|
||||
@@ -37,12 +37,20 @@
|
||||
<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>
|
||||
<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>
|
||||
<div id="spinner" class="spinner-border secondary-primary htmx-indicator position-absolute top-50 start-50" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<div style="text-align:center">Quick Links:
|
||||
{% if site_config["site"]["nodes"] == "True" %}<a href="/nodelist">Nodes</a> - {% endif %}
|
||||
{% if site_config["site"]["conversations"] == "True" %}<a href="/chat">Conversations</a> - {% endif %}
|
||||
{% if site_config["site"]["everything"] == "True" %}<a href="/firehose">See <strong>everything</strong></a> - {% endif %}
|
||||
{% if site_config["site"]["graph_lf"] == "True" %} Mesh Graph: <a href="/nodegraph/LongFast">LF</a> - {% endif %}
|
||||
{% if site_config["site"]["graph_ms"] == "True" %}<a href="/nodegraph/MediumSlow">MS</a> - {% endif %}
|
||||
{% if site_config["site"]["graph_mf"] == "True" %}<a href="/nodegraph/MediumFast">MF</a> - {% endif %}
|
||||
{% if site_config["site"]["net"] == "True" %}<a href="/net">Weekly Net</a> - {% endif %}
|
||||
{% if site_config["site"]["map"] == "True" %}<a href="/map">Map</a> - {% endif %}
|
||||
{% if site_config["site"]["stats"] == "True" %}<a href="/stats">Stats</a> - {% endif %}
|
||||
{% if site_config["site"]["top"] == "True" %}<a href="/top">Top Traffic</a>{% endif %}
|
||||
</div><br>
|
||||
|
||||
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
<br><div style="text-align:center">Visit <strong><a href="https://github.com/pablorevilla-meshtastic/meshview">Meshview</a></strong> on Github. Also visit the original <a href="https://github.com/armooo/meshview">Meshview</a> by Armooo.</div><br>
|
||||
|
||||
@@ -34,10 +34,7 @@
|
||||
<div id="map" style="width: 100%; height: 600px;"></div>
|
||||
|
||||
<div id="filter-container">
|
||||
<input type="checkbox" class="filter-checkbox" id="filter-longfast" checked> LongFast
|
||||
<input type="checkbox" class="filter-checkbox" id="filter-mediumslow" checked> MediumSlow
|
||||
<input type="checkbox" class="filter-checkbox" id="filter-router-longfast" checked> LongFast Routers
|
||||
<input type="checkbox" class="filter-checkbox" id="filter-router-mediumslow" checked> MediumSlow Routers
|
||||
<!-- Filters will be dynamically generated here -->
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
|
||||
@@ -52,8 +49,9 @@
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}).addTo(map);
|
||||
|
||||
var markers = { LongFast: [], MediumSlow: [], RouterLongFast: [], RouterMediumSlow: [] };
|
||||
var markers = {};
|
||||
var bounds = L.latLngBounds();
|
||||
var channels = new Set(); // Stores unique channels
|
||||
|
||||
var nodes = [
|
||||
{% for node in nodes %}
|
||||
@@ -86,18 +84,33 @@
|
||||
return seconds + "s";
|
||||
}
|
||||
|
||||
// Function to generate a unique color from a string (channel name)
|
||||
function hashToColor(str) {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
||||
}
|
||||
let hue = hash % 360; // Keep hue in 0-360 range
|
||||
return `hsl(${hue}, 80%, 50%)`; // Use HSL for vibrant colors
|
||||
}
|
||||
|
||||
nodes.forEach(function(node) {
|
||||
if (node.lat !== null && node.long !== null) {
|
||||
let category = node.channel.toLowerCase().includes("mediumslow") ? "MediumSlow" : "LongFast";
|
||||
let color = category === "MediumSlow" ? "#0000ff" : "#ff0000";
|
||||
let category = node.channel;
|
||||
let isRouter = node.role.toLowerCase().includes("router");
|
||||
|
||||
// Store the unique channel
|
||||
channels.add(category);
|
||||
|
||||
// Generate a unique color for the channel
|
||||
let color = hashToColor(category);
|
||||
|
||||
let markerOptions = {
|
||||
radius: isRouter ? 9 : 7,
|
||||
color: "white",
|
||||
fillColor: color,
|
||||
fillOpacity: 1,
|
||||
weight: .7,
|
||||
weight: 0.7,
|
||||
};
|
||||
|
||||
var popupContent = `
|
||||
@@ -110,40 +123,43 @@
|
||||
if (node.firmware) popupContent += `<b>Firmware:</b> ${node.firmware}<br>`;
|
||||
|
||||
var marker = L.circleMarker([node.lat, node.long], markerOptions).bindPopup(popupContent);
|
||||
|
||||
marker.addTo(map);
|
||||
|
||||
if (isRouter) {
|
||||
if (category === "LongFast") {
|
||||
markers.RouterLongFast.push(marker);
|
||||
} else {
|
||||
markers.RouterMediumSlow.push(marker);
|
||||
}
|
||||
} else {
|
||||
markers[category].push(marker);
|
||||
}
|
||||
if (!markers[category]) markers[category] = [];
|
||||
markers[category].push(marker);
|
||||
|
||||
bounds.extend(marker.getLatLng());
|
||||
}
|
||||
});
|
||||
|
||||
// Fit map to bounds
|
||||
var bayAreaBounds = [
|
||||
[{{ site_config["site"]["map_top_left_lat"] }}, {{ site_config["site"]["map_top_left_lon"] }}],
|
||||
[{{ site_config["site"]["map_bottom_right_lat"] }}, {{ site_config["site"]["map_bottom_right_lon"] }}]
|
||||
];
|
||||
map.fitBounds(bayAreaBounds);
|
||||
|
||||
// Generate dynamic filters
|
||||
let filterContainer = document.getElementById("filter-container");
|
||||
|
||||
channels.forEach(channel => {
|
||||
let filterId = `filter-${channel.replace(/\s+/g, '-').toLowerCase()}`;
|
||||
let color = hashToColor(channel);
|
||||
let filterHtml = `
|
||||
<label style="color:${color};">
|
||||
<input type="checkbox" class="filter-checkbox" id="${filterId}" checked> ${channel}
|
||||
</label>
|
||||
`;
|
||||
filterContainer.innerHTML += filterHtml;
|
||||
});
|
||||
|
||||
function updateMarkers() {
|
||||
let showLongFast = document.getElementById("filter-longfast").checked;
|
||||
let showMediumSlow = document.getElementById("filter-mediumslow").checked;
|
||||
let showRouterLongFast = document.getElementById("filter-router-longfast").checked;
|
||||
let showRouterMediumSlow = document.getElementById("filter-router-mediumslow").checked;
|
||||
channels.forEach(channel => {
|
||||
let filterId = `filter-${channel.replace(/\s+/g, '-').toLowerCase()}`;
|
||||
let isChecked = document.getElementById(filterId).checked;
|
||||
|
||||
markers.LongFast.forEach(m => showLongFast ? map.addLayer(m) : map.removeLayer(m));
|
||||
markers.MediumSlow.forEach(m => showMediumSlow ? map.addLayer(m) : map.removeLayer(m));
|
||||
markers.RouterLongFast.forEach(m => showRouterLongFast ? map.addLayer(m) : map.removeLayer(m));
|
||||
markers.RouterMediumSlow.forEach(m => showRouterMediumSlow ? map.addLayer(m) : map.removeLayer(m));
|
||||
markers[channel].forEach(m => isChecked ? map.addLayer(m) : map.removeLayer(m));
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll(".filter-checkbox").forEach(input => {
|
||||
@@ -151,4 +167,5 @@
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -26,6 +26,8 @@ import gc
|
||||
from meshview import config
|
||||
import json
|
||||
|
||||
from meshview.store import get_total_node_count
|
||||
|
||||
CONFIG = config.CONFIG
|
||||
|
||||
env = Environment(loader=PackageLoader("meshview"), autoescape=select_autoescape())
|
||||
@@ -1191,8 +1193,8 @@ async def stats(request):
|
||||
total_packets = await store.get_total_packet_count()
|
||||
total_nodes = await store.get_total_node_count()
|
||||
total_packets_seen = await store.get_total_packet_seen_count()
|
||||
total_nodes_longfast = await store.get_total_node_count_longfast()
|
||||
total_nodes_mediumslow = await store.get_total_node_count_mediumslow()
|
||||
total_nodes_longfast = await get_total_node_count("LongFast")
|
||||
total_nodes_mediumslow = await get_total_node_count("MediumSlow")
|
||||
print_memory_usage()
|
||||
template = env.get_template("stats.html")
|
||||
return web.Response(
|
||||
@@ -1208,7 +1210,7 @@ async def stats(request):
|
||||
)
|
||||
except Exception as e:
|
||||
return web.Response(
|
||||
text="An error occurred while processing your request.",
|
||||
text=f"An error occurred: {str(e)}",
|
||||
status=500,
|
||||
content_type="text/plain",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user