mirror of
https://github.com/pablorevilla-meshtastic/meshview.git
synced 2026-03-04 23:27:46 +01:00
added channel filtering min_packets, and allowlist, fixed javascript error, new sample.config.ini sections
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
2025-10-14 20:13:45,221 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-14 20:25:47,645 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-14 20:34:48,026 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-14 21:11:16,069 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-14 21:19:58,777 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-14 21:20:29,595 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-15 10:28:37,193 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-15 15:54:56,829 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-15 15:59:16,304 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-15 16:27:05,307 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-15 16:29:14,882 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-15 17:04:31,298 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-15 17:11:28,215 [INFO] Daily cleanup is disabled by configuration.
|
||||
2025-10-15 18:00:31,833 [INFO] Daily cleanup is disabled by configuration.
|
||||
@@ -384,11 +384,15 @@ async def get_packet_stats(
|
||||
}
|
||||
|
||||
|
||||
async def get_channels_in_period(period_type: str = "hour", length: int = 24):
|
||||
async def get_channels_in_period(period_type: str = "hour", length: int = 24, min_packets: int = 5, allowlist: list[str] | None = None):
|
||||
"""
|
||||
Returns a list of distinct channels used in packets over a given period.
|
||||
Returns a list of distinct channels used in packets over a given period,
|
||||
filtered to only include channels with at least min_packets packets.
|
||||
|
||||
period_type: "hour" or "day"
|
||||
length: number of hours or days to look back
|
||||
min_packets: minimum number of packets a channel must have to be included (default: 5)
|
||||
allowlist: optional list of allowed channel names. If None or contains '*', all channels are allowed
|
||||
"""
|
||||
now = datetime.now()
|
||||
|
||||
@@ -400,13 +404,23 @@ async def get_channels_in_period(period_type: str = "hour", length: int = 24):
|
||||
raise ValueError("period_type must be 'hour' or 'day'")
|
||||
|
||||
async with database.async_session() as session:
|
||||
# Count packets per channel and filter by minimum packet count
|
||||
q = (
|
||||
select(Packet.channel)
|
||||
select(Packet.channel, func.count(Packet.id).label('packet_count'))
|
||||
.where(Packet.import_time >= start_time)
|
||||
.distinct()
|
||||
.where(Packet.channel.isnot(None))
|
||||
.group_by(Packet.channel)
|
||||
.having(func.count(Packet.id) >= min_packets)
|
||||
.order_by(Packet.channel)
|
||||
)
|
||||
|
||||
result = await session.execute(q)
|
||||
channels = [row[0] for row in result if row[0] is not None]
|
||||
channels = [row[0] for row in result]
|
||||
|
||||
# Apply allowlist filtering if specified
|
||||
if allowlist and '*' not in allowlist:
|
||||
# Filter to only include channels in the allowlist (case-insensitive)
|
||||
allowlist_lower = [ch.lower() for ch in allowlist]
|
||||
channels = [ch for ch in channels if ch.lower() in allowlist_lower]
|
||||
|
||||
return channels
|
||||
|
||||
@@ -243,25 +243,23 @@ nodes.forEach(n=>{
|
||||
}
|
||||
});
|
||||
|
||||
const tracerouteChannelCounts = new Map();
|
||||
const channelCounts = new Map();
|
||||
edges.forEach(edge=>{
|
||||
if(edge.type === 'traceroute'){
|
||||
const weight = typeof edge.weight === 'number' ? edge.weight : 1;
|
||||
const fromChannel = channelByNodeId.get(String(edge.source));
|
||||
const toChannel = channelByNodeId.get(String(edge.target));
|
||||
if(fromChannel){
|
||||
tracerouteChannelCounts.set(fromChannel, (tracerouteChannelCounts.get(fromChannel) || 0) + weight);
|
||||
}
|
||||
if(toChannel){
|
||||
tracerouteChannelCounts.set(toChannel, (tracerouteChannelCounts.get(toChannel) || 0) + weight);
|
||||
}
|
||||
const weight = typeof edge.weight === 'number' ? edge.weight : 1;
|
||||
const fromChannel = channelByNodeId.get(String(edge.source));
|
||||
const toChannel = channelByNodeId.get(String(edge.target));
|
||||
if(fromChannel){
|
||||
channelCounts.set(fromChannel, (channelCounts.get(fromChannel) || 0) + weight);
|
||||
}
|
||||
if(toChannel){
|
||||
channelCounts.set(toChannel, (channelCounts.get(toChannel) || 0) + weight);
|
||||
}
|
||||
});
|
||||
|
||||
let channelOptions = [];
|
||||
if (tracerouteChannelCounts.size) {
|
||||
if (channelCounts.size) {
|
||||
channelOptions = Array.from(
|
||||
[...tracerouteChannelCounts.entries()]
|
||||
[...channelCounts.entries()]
|
||||
.filter(([_, count]) => count > 0)
|
||||
.map(([channel]) => channel)
|
||||
).sort();
|
||||
@@ -388,10 +386,8 @@ function searchNode(){
|
||||
else alert("Node not found in current channel!");
|
||||
}
|
||||
|
||||
initializeChannelOptions().then(() => {
|
||||
populateChannelDropdown();
|
||||
filterByChannel(true);
|
||||
});
|
||||
populateChannelDropdown();
|
||||
filterByChannel(true);
|
||||
window.addEventListener('resize', ()=>chart.resize());
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1510,9 +1510,29 @@ async def get_config(request):
|
||||
async def api_channels(request: web.Request):
|
||||
period_type = request.query.get("period_type", "hour")
|
||||
length = int(request.query.get("length", 24))
|
||||
|
||||
# Get min_packets from config, with fallback to query param or default
|
||||
config_min_packets = CONFIG.get("site", {}).get("min_packets_for_channel", "5")
|
||||
try:
|
||||
default_min_packets = int(config_min_packets)
|
||||
except (ValueError, TypeError):
|
||||
default_min_packets = 5
|
||||
|
||||
min_packets = int(request.query.get("min_packets", default_min_packets))
|
||||
|
||||
# Get channel allowlist from config
|
||||
allowlist_str = CONFIG.get("site", {}).get("channel_allowlist", "*")
|
||||
if allowlist_str and allowlist_str.strip():
|
||||
# Parse comma-separated list, or use '*' for all
|
||||
if allowlist_str.strip() == "*":
|
||||
allowlist = None # None means all channels allowed
|
||||
else:
|
||||
allowlist = [ch.strip() for ch in allowlist_str.split(",") if ch.strip()]
|
||||
else:
|
||||
allowlist = None
|
||||
|
||||
try:
|
||||
channels = await store.get_channels_in_period(period_type, length)
|
||||
channels = await store.get_channels_in_period(period_type, length, min_packets, allowlist)
|
||||
return web.json_response({"channels": channels})
|
||||
except Exception as e:
|
||||
return web.json_response({"channels": [], "error": str(e)})
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# -------------------------
|
||||
# Server Configuration
|
||||
# -------------------------
|
||||
# important: no leading spaces on configuration lines.
|
||||
|
||||
[server]
|
||||
# The address to bind the server to. Use * to listen on all interfaces.
|
||||
bind = *
|
||||
@@ -59,6 +61,17 @@ firehose_interal=3
|
||||
weekly_net_message = Weekly Mesh check-in. We will keep it open on every Wednesday from 5:00pm for checkins. The message format should be (LONG NAME) - (CITY YOU ARE IN) #BayMeshNet.
|
||||
net_tag = #BayMeshNet
|
||||
|
||||
# Channel filtering configuration
|
||||
# Minimum number of packets required for a channel to appear in dropdowns
|
||||
min_packets_for_channel = 5
|
||||
|
||||
# Channel allowlist: comma-separated list of channels to display, or * for all channels
|
||||
# Use * to show all channels with sufficient packets
|
||||
# Or specify channels like: LongFast,MediumSlow,MediumFast,ShortTurbo,LongSlow,ShortFast,ShortSlow,VLongSlow
|
||||
channel_allowlist = *
|
||||
# Examples of common Meshtastic channels:
|
||||
#channel_allowlist = LongFast,MediumSlow,MediumFast,ShortTurbo,LongSlow,ShortFast,ShortSlow,VLongSlow
|
||||
|
||||
# -------------------------
|
||||
# MQTT Broker Configuration
|
||||
# -------------------------
|
||||
|
||||
Reference in New Issue
Block a user