feat(config): Online-Schwellwert konfigurierbar (web.online_threshold)

- config.yaml: neuer Parameter web.online_threshold (Default: 900 s)
- /api/stats und WS stats_update liefern online_threshold
- dashboard.js: isOnline() nutzt onlineThreshold aus Stats-API
- bot.py (?mesh) und database.py (nodes_online) nutzen Config-Wert
Closes #12.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ppfeiffer 2026-02-20 15:17:05 +01:00
parent a5ab4550f2
commit 644d2d00ba
6 changed files with 25 additions and 4 deletions

View file

@ -1,5 +1,17 @@
# Changelog
## [0.08.15] - 2026-02-20
### Added
- **`web.online_threshold`** in `config.yaml` (Default: 900 s): Online-Schwellwert zentral
konfigurierbar; Änderung in der Config wirkt sofort auf alle Stellen (closes #12).
- **`/api/stats`** liefert `online_threshold` Frontend liest Wert vom Backend.
### Changed
- `meshbot/bot.py`: `?mesh`-Kommando nutzt `config.get("web.online_threshold", 900)`.
- `meshbot/database.py`: `nodes_online`-Abfrage nutzt konfigurierten Schwellwert.
- `static/js/dashboard.js`: `isOnline()` nutzt `onlineThreshold` aus Stats-API statt hardcodierter 900.
## [0.08.14] - 2026-02-20
### Added

View file

@ -1,4 +1,4 @@
version: "0.08.14"
version: "0.08.15"
bot:
name: "MeshDD-Bot"
@ -11,6 +11,7 @@ meshtastic:
web:
host: "0.0.0.0"
port: 8081
online_threshold: 900
database:
path: "meshdd.db"

View file

@ -563,7 +563,8 @@ class MeshBot:
nodes = await self.db.get_all_nodes()
total = len(nodes)
now = time.time()
online = sum(1 for n in nodes if n.get("last_seen") and now - n["last_seen"] < 900)
threshold = config.get("web.online_threshold", 900)
online = sum(1 for n in nodes if n.get("last_seen") and now - n["last_seen"] < threshold)
active_24h = sum(1 for n in nodes if n.get("last_seen") and now - n["last_seen"] < 86400)
with_pos = sum(1 for n in nodes if n.get("lat") and n.get("lon"))

View file

@ -2,6 +2,8 @@ import aiosqlite
import time
import logging
from meshbot import config
logger = logging.getLogger(__name__)
@ -207,8 +209,9 @@ class Database:
"SELECT COUNT(*) FROM nodes WHERE last_seen >= ?", (day_ago,)
) as c:
stats["nodes_24h"] = (await c.fetchone())[0]
threshold = config.get("web.online_threshold", 900)
async with self.db.execute(
"SELECT COUNT(*) FROM nodes WHERE last_seen >= ?", (now - 900,)
"SELECT COUNT(*) FROM nodes WHERE last_seen >= ?", (now - threshold,)
) as c:
stats["nodes_online"] = (await c.fetchone())[0]
async with self.db.execute(

View file

@ -110,6 +110,7 @@ class WebServer:
my_id = self.bot.get_my_node_id() if self.bot else None
stats = await self.db.get_stats(my_node_id=my_id)
stats["version"] = config.get("version", "0.00.00")
stats["online_threshold"] = config.get("web.online_threshold", 900)
if self.bot:
stats["uptime"] = self.bot.get_uptime()
stats["bot_connected"] = self.bot.is_connected()
@ -159,6 +160,7 @@ class WebServer:
my_id = self.bot.get_my_node_id() if self.bot else None
stats = await self.db.get_stats(my_node_id=my_id)
stats["version"] = config.get("version", "0.00.00")
stats["online_threshold"] = config.get("web.online_threshold", 900)
if self.bot:
stats["uptime"] = self.bot.get_uptime()
stats["bot_connected"] = self.bot.is_connected()

View file

@ -12,6 +12,7 @@ let nodeSearch = '';
let nodeOnlineFilter = false;
let nodeSortKey = 'last_seen';
let nodeSortDir = -1;
let onlineThreshold = 900;
let chartChannel = null;
let chartHops = null;
let chartHardware = null;
@ -163,6 +164,7 @@ function updateBotStatus(status) {
function updateStats(stats) {
lastStats = stats;
if (stats.online_threshold != null) onlineThreshold = stats.online_threshold;
if (stats.version) {
document.getElementById('versionLabel').textContent = `v${stats.version}`;
}
@ -187,7 +189,7 @@ function updateStats(stats) {
function isOnline(lastSeen) {
if (!lastSeen) return false;
return (Date.now() / 1000 - lastSeen) < 900; // < 15 min
return (Date.now() / 1000 - lastSeen) < onlineThreshold;
}
function timeAgo(timestamp) {