From 0a7f7f718e859db0c2cd38fcd616641fa206b820 Mon Sep 17 00:00:00 2001 From: Roby Date: Sun, 26 Apr 2026 23:37:43 +0200 Subject: [PATCH] feat: implement dynamic Callsign and Radio ID from MQTT General topic - Node names and IDs are now automatically updated using MMDVMHost/General data - Added fallback to clients.json values if node is offline or data is missing - Improved UI with dynamic badge coloring and high-contrast text for IDs --- app.py | 21 +++++++++++++++++++-- templates/index.html | 24 ++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/app.py b/app.py index c039e67..7eaf932 100644 --- a/app.py +++ b/app.py @@ -152,6 +152,7 @@ device_health = {} last_seen_reflector = {} network_mapping = {} node_info = {} +node_general = {} if os.path.exists(CACHE_FILE): try: @@ -301,7 +302,8 @@ def on_message(client, userdata, msg): except Exception as e: logger.error(f"Error parsing DMRGateway for {cid}: {e}") - + + # --- MMDVMHOST INFO MANAGEMENT (FREQUENZE & LOCATION) --- elif len(parts) >= 4 and parts[0] == 'data' and parts[2].lower() == 'mmdvmhost' and parts[3].lower() == 'info': try: cid = parts[1].lower() @@ -332,6 +334,20 @@ def on_message(client, userdata, msg): except Exception as e: logger.error(f"Error parsing MMDVMHost info for {cid}: {e}") + # --- MMDVMHOST GENERAL MANAGEMENT (CALLSIGN & ID) --- + elif len(parts) >= 4 and parts[0] == 'data' and parts[2].lower() == 'mmdvmhost' and parts[3].lower() == 'general': + try: + cid = parts[1].lower() + data = json.loads(payload) + callsign = data.get("Callsign", "") + radio_id = data.get("Id", "") + + if callsign: + node_general[cid] = {"callsign": callsign, "radio_id": radio_id} + socketio.emit('dati_aggiornati') + except Exception as e: + logger.error(f"Error parsing MMDVMHost general for {cid}: {e}") + # --- OTHER GATEWAYS MANAGEMENT --- elif parts[0] in ['dmr-gateway', 'nxdn-gateway', 'ysf-gateway', 'p25-gateway', 'dstar-gateway']: data = json.loads(payload) @@ -462,7 +478,8 @@ def get_states(): "telemetry": client_telemetry, "health": device_health, "networks": network_mapping, - "info": node_info + "info": node_info, + "general": node_general }) @app.route('/api/stats') diff --git a/templates/index.html b/templates/index.html index 3fe8217..1a65ee3 100644 --- a/templates/index.html +++ b/templates/index.html @@ -670,10 +670,31 @@ const statusDiv = document.getElementById(`status-${c.id}`); const cardDiv = document.getElementById(`card-${c.id}`); if (!statusDiv || !cardDiv) return; + // 1. PRIMA CALCOLIAMO SE È ONLINE let stateValue = data.states[c.id.toLowerCase()] || data.states[c.id] || "OFFLINE"; stateValue = String(stateValue).trim().toUpperCase(); statusDiv.innerText = stateValue; const isOnline = !stateValue.includes("OFF") && stateValue !== ""; + // 2. POI AGGIORNIAMO NOME E ID DINAMICI + let genObj = data.general && data.general[c.id.toLowerCase()]; + const nameSpan = cardDiv.querySelector('.client-name'); + const idBadge = cardDiv.querySelector('.badge-id'); + + if (genObj && isOnline) { + nameSpan.innerText = genObj.callsign; + idBadge.innerText = `ID: ${genObj.radio_id}`; + idBadge.style.background = "var(--primary)"; + idBadge.style.color = "#ffffff"; // <--- FORZA IL TESTO BIANCO + idBadge.style.borderColor = "var(--primary)"; // <--- ADATTA IL BORDO + } else { + nameSpan.innerText = c.name; + idBadge.innerText = `ID: ${c.id.toUpperCase()}`; + idBadge.style.background = "rgba(255,255,255,0.1)"; + idBadge.style.color = "var(--text-muted)"; // <--- RIPRISTINA IL GRIGIO + idBadge.style.borderColor = "var(--border-color)"; + } + + // 3. TELEMETRIA E STATO (PULITO DAI DUPLICATI) let telemetryObj = data.telemetry[c.id.toLowerCase()] || data.telemetry[c.id] || { ts1: "...", ts2: "...", alt: "", idle: true }; if (typeof telemetryObj === 'string') telemetryObj = { ts1: telemetryObj, ts2: "...", alt: "", idle: true }; @@ -717,7 +738,6 @@ } let healthObj = data.health && data.health[c.id.toLowerCase()]; - // --- INIZIO BLOCCO INFO AGGIUNTIVE (FREQ + LOC) --- let infoObj = data.info && data.info[c.id.toLowerCase()]; const freqContainer = document.getElementById(`freq-container-${c.id}`); const freqTx = document.getElementById(`freq-tx-${c.id}`); @@ -743,7 +763,7 @@ if (freqContainer) freqContainer.style.display = 'none'; if (metaContainer) metaContainer.style.display = 'none'; } - // --- FINE BLOCCO INFO AGGIUNTIVE --- + const healthContainer = document.getElementById(`health-${c.id}`); const cpuSpan = document.getElementById(`cpu-${c.id}`); const tempSpan = document.getElementById(`temp-${c.id}`); const ramSpan = document.getElementById(`ram-${c.id}`); const diskSpan = document.getElementById(`disk-${c.id}`); if (healthObj && isOnline) {