|
- 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()
|