import streamlit as st import pandas as pd import json from PIL import Image, ImageDraw, ImageFont from pathlib import Path import time import os def show_inference_page(cfg): # Definizione percorsi # Assumendo che il file sia in /app/app/web_inference.py, # cerchiamo il font nella stessa cartella 'app' BASE_DIR = Path(__file__).parent MAPS_DIR = Path(cfg['maps']['map_dir']) INFER_FILE = Path(cfg['infer']['output_dir']) / cfg['infer']['out_file'] # Percorso del font locale FONT_PATH = BASE_DIR / "DejaVuSans-Bold.ttf" st.subheader("🤖 Monitoraggio Inferenza Live") # --- CONTROLLI NEL TAB --- with st.expander("🎨 Opzioni e Controllo", expanded=True): col_ctrl1, col_ctrl2, col_ctrl3, col_ctrl4 = st.columns(4) with col_ctrl1: dot_size = st.slider("Dimensione Marker", 10, 100, 45, key="inf_dot") with col_ctrl2: refresh_rate = st.select_slider("Refresh (s)", options=[2, 5, 10, 30], value=5, key="inf_ref") with col_ctrl3: show_labels = st.checkbox("Mostra MAC", value=True, key="inf_show_mac") with col_ctrl4: # Monitoraggio disattivato di default per evitare login fantasma auto_refresh = st.toggle("🔄 Monitoraggio Attivo", value=False, key="inf_auto") floor_id = st.number_input("Piano (Z)", value=0, min_value=0, step=1, key="inf_z") # Caricamento Metadati meta_path = MAPS_DIR / f"{cfg['maps']['meta_prefix']}{floor_id}.json" meta = {"pixel_ratio": 1.0, "origin": [0, 0]} if meta_path.exists(): with open(meta_path, "r") as f: meta.update(json.load(f)) try: if INFER_FILE.exists(): df = pd.read_csv(INFER_FILE, sep=";") df_active = df[(df['z'] == floor_id) & (df['x'] != -1) & (df['y'] != -1)] img_path = MAPS_DIR / f"{cfg['maps']['floor_prefix']}{floor_id}.png" if img_path.exists(): img = Image.open(img_path).convert("RGBA") draw = ImageDraw.Draw(img) # --- GESTIONE FONT XL --- # Dimensione proporzionale al pallino (1.5x) dynamic_font_size = int(dot_size * 1.5) font = None if FONT_PATH.exists(): try: # Tenta il caricamento del file TTF locale font = ImageFont.truetype(str(FONT_PATH), dynamic_font_size) except Exception as e: # Se il file è corrotto (unknown file format), mostra errore e usa fallback st.error(f"Errore caricamento font: {e}. Controlla il file DejaVuSans-Bold.ttf") if font is None: font = ImageFont.load_default() for _, row in df_active.iterrows(): px_x = (row['x'] * meta["pixel_ratio"]) + meta["origin"][0] px_y = (row['y'] * meta["pixel_ratio"]) + meta["origin"][1] r = dot_size # Disegno Marker draw.ellipse([px_x-(r+5), px_y-(r+5), px_x+(r+5), px_y+(r+5)], fill="black") draw.ellipse([px_x-r, px_y-r, px_x+r, px_y+r], fill="#00E5FF") if show_labels: label = f"{str(row['mac'])[-5:]}" # Posizionamento dinamico a destra del pallino text_x = px_x + r + 20 text_y = px_y - (dynamic_font_size / 2) # Outline per leggibilità (bordo nero spesso 3px) for dx, dy in [(-3,-3), (3,-3), (-3,3), (3,3), (0,-3), (0,3), (-3,0), (2,0)]: draw.text((text_x + dx, text_y + dy), label, font=font, fill="black") # Testo Giallo draw.text((text_x, text_y), label, font=font, fill="#FFFF00") st.image(img, use_column_width=True) st.metric("Dispositivi Online", len(df_active)) except Exception as e: st.error(f"Errore generale: {e}") # --- REFRESH CONDIZIONALE --- if auto_refresh: time.sleep(refresh_rate) st.rerun()