import streamlit as st import pandas as pd import psutil import os import time import json import paho.mqtt.client as mqtt import requests def get_system_metrics(): """Recupera statistiche hardware del server.""" return { "cpu": psutil.cpu_percent(interval=None), "ram": psutil.virtual_memory().percent, "disk": psutil.disk_usage('/').percent, "net_recv": psutil.net_io_counters().bytes_recv / (1024**2) } def get_api_data(cfg, sec): """Fetch reale dei beacon dalle API OIDC.""" if not sec or 'oidc' not in sec: return None, "Segreti mancanti" try: auth_res = requests.post( cfg['api']['token_url'], data={ "grant_type": "password", "client_id": cfg['api']['client_id'], "client_secret": sec['oidc']['client_secret'], "username": sec['oidc']['username'], "password": sec['oidc']['password'], }, verify=cfg['api'].get('verify_tls', False), timeout=5 ) token = auth_res.json().get("access_token") res = requests.get( cfg['api']['get_beacons_url'], headers={"Authorization": f"Bearer {token}"}, verify=cfg['api'].get('verify_tls', False), timeout=5 ) return res.json(), "OK" except Exception as e: return None, str(e) def show_system_status(cfg, sec=None): st.title("🛰️ Diagnostica & Sniffer") # --- 1. RISORSE DI SISTEMA --- st.subheader("🖥️ Risorse Hardware") m = get_system_metrics() c1, c2, c3, c4 = st.columns(4) c1.metric("CPU", f"{m['cpu']}%") c2.metric("RAM", f"{m['ram']}%") c3.metric("Disco", f"{m['disk']}%") c4.metric("Rete", f"{m['net_recv']:.1f} MB") st.divider() # --- 2. CONNETTIVITÀ & DATI API --- st.subheader("🔌 Connettività & API") col_api, col_mq = st.columns(2) with col_api: st.markdown("**Server API OIDC**") beacons_api_data, api_msg = get_api_data(cfg, sec) if beacons_api_data: st.success(f"✅ Connesso ({len(beacons_api_data)} beacon)") with st.expander("Visualizza Tabella Dati API"): # Mostriamo i dati API in una tabella senza scroll eccessivo df_api = pd.DataFrame(beacons_api_data) st.table(df_api.head(10)) else: st.error(f"❌ Errore: {api_msg}") with col_mq: st.markdown("**Broker MQTT**") mq_host = cfg.get('mqtt', {}).get('host', '127.0.0.1') st.info(f"Host: `{mq_host}`") st.success("✅ Configurazione Caricata") st.divider() # --- 3. SNIFFER DATI MQTT --- st.subheader("🎯 Sniffer Real-Time") st.caption("Inserisci un MAC per intercettare il traffico live (10 secondi)") target_mac = st.text_input("MAC da sniffare (es. ac233fc1dd49)", "").lower().replace(":", "") if st.button("🚀 AVVIA CATTURA", use_container_width=True, type="primary"): if not target_mac: st.warning("Inserisci un MAC prima di iniziare.") else: captured = [] def on_message(client, userdata, message): payload = message.payload.decode() topic = message.topic if target_mac in topic.lower() or target_mac in payload.lower(): captured.append({ "Ora": time.strftime("%H:%M:%S"), "Topic": topic, "Dati": payload[:100] + "..." # Accorciamo per la tabella }) client = mqtt.Client(client_id=f"Sniffer_{int(time.time())}") try: client.on_message = on_message client.connect(cfg['mqtt']['host'], cfg['mqtt']['port'], 60) client.subscribe("#") client.loop_start() with st.status("Cattura in corso...") as status: progress = st.progress(0) for i in range(100): time.sleep(0.1) progress.progress(i + 1) client.loop_stop() status.update(label="Cattura completata!", state="complete") if captured: st.success(f"Intercettati {len(captured)} messaggi per `{target_mac}`") # Usiamo st.table per evitare le slidebar (renderizza tutto il contenuto) st.table(pd.DataFrame(captured)) else: st.warning("Nessun messaggio trovato. Controlla che il dispositivo sia acceso.") except Exception as e: st.error(f"Connessione fallita: {e}")