"""Pannello LED iPIXEL: scritte, immagini, luminosità, orologio, accensione. Lo stato di LuZa e le notifiche compaiono da soli se l'opzione è attiva nelle impostazioni (scheda Casa).""" from __future__ import annotations import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from avatar import ipixel # noqa: E402 def _p(): if ipixel.panel is None: raise RuntimeError("pannello iPIXEL non attivo: abilitalo nelle impostazioni (scheda Casa)") return ipixel.panel def scrivi(params: dict, ctx: dict) -> str: testo = str(params.get("testo") or "").strip() if not testo: return "Errore: serve il testo." col = ipixel.NOMI_COLORI.get(str(params.get("colore") or "").lower(), None) durata = float(params.get("secondi") or 30) _p().show_text(testo, col, durata) return f"Sul pannello: «{testo}» per {int(durata)} secondi." def immagine(params: dict, ctx: dict) -> str: path = str(params.get("percorso") or "").strip() if not Path(path).expanduser().is_file(): return "Errore: file immagine non trovato." _p().show_image(str(Path(path).expanduser()), float(params.get("secondi") or 30)) return "Immagine inviata al pannello." def luminosita(params: dict, ctx: dict) -> str: v = max(1, min(int(params.get("livello") or 40), 100)) _p().run_cmd([5, 0, 4, 0x80, v]) _p().settings.set("ipixel_luminosita", v); _p().settings.save() return f"Luminosità del pannello al {v}%." def accendi(params: dict, ctx: dict) -> str: on = str(params.get("acceso", True)).lower() not in ("false", "0", "no") _p().run_cmd([5, 0, 7, 1, 1 if on else 0]) return "Pannello acceso." if on else "Pannello spento." def orologio(params: dict, ctx: dict) -> str: _p().clock() return "Il pannello mostra l'orologio." def stato(params: dict, ctx: dict) -> str: p = ipixel.panel if p is None: return "Pannello iPIXEL disattivato nelle impostazioni." return (f"Pannello {'collegato' if p.connected else 'non collegato'} ({p.size[0]}×{p.size[1]})" + (f", errore: {p.error}" if p.error and not p.connected else "") + ".") def animazione(params: dict, ctx: dict) -> str: from avatar import ipixel_fun as fun import time nome = str(params.get("nome") or "").lower() p = _p() if nome in fun.ANIMAZIONI: data = fun.ANIMAZIONI[nome](p.size) with p._lock: p._want = (f"fun:{time.time()}", data, True); p._notify_until = time.time() + float(params.get("secondi") or 15) p._shown_key = None; p._poke() return f"Animazione «{nome}» sul pannello." kind, val = fun.scegli(p.size) if kind == "gif": with p._lock: p._want = (f"fun:{time.time()}", val, True); p._notify_until = time.time() + 15 p._shown_key = None; p._poke(); return "Sorpresa animata sul pannello." p.show_text(str(val), None, 12) return f"Sul pannello: «{val}»." def demo(params: dict, ctx: dict) -> str: """Sequenza dimostrativa sul pannello, in background (circa 90 secondi).""" import threading, time from avatar import ipixel_fun as fun def run(): p = _p() steps = [ ("stato", "THINKING · penso", 4), ("stato", "THINKING · genero la risposta · 42 token · 38/s", 3), ("stato", "THINKING · genero la risposta · 187 token · 51/s", 3), ("stato", "PROCESSING · strumento: meteo", 4), ("stato", "SPEAKING", 4), ("stato", "LISTENING", 3), ("testo", "WA Valentina: amo stasera ceniamo fuori?", 10), ("allarme", "Server i5: disco al 91%", 9), ("anim", "plasma", 7), ("anim", "pacman", 7), ("anim", "cuore", 6), ("anim", "matrix", 6), ("testo", "Più bpm, meno stress", 8), ("musica", "", 22), ("fine", "", 0), ] for kind, val, dur in steps: if kind == "stato": p.on_state(val) elif kind in ("testo", "allarme"): p.show_text(val, ipixel.COLORI["ALERT"] if kind == "allarme" else None, dur, icon=ipixel.COLORI["ALERT"] if kind == "allarme" else None) elif kind == "anim": data = fun.ANIMAZIONI[val](p.size) with p._lock: p._want = (f"demo:{val}:{time.time()}", data, True); p._notify_until = time.time() + dur p._shown_key = None; p._poke() elif kind == "musica": p.on_state("LISTENING") with p._lock: p._notify_until = 0; p._want = None p.set_background("demo:music", ipixel.render_music("Bohemian Rhapsody", "Queen", 61, 354, p.size, dur), True, dur) elif kind == "fine": p.clear_background(); p.clock() time.sleep(dur) threading.Thread(target=run, daemon=True, name="ipixel-demo").start() return "Demo avviata sul pannello: stati di LuZa, notifiche, animazioni e schermata musica, circa un minuto e mezzo." TOOLS = [ {"name": "ipixel_demo", "description": "Mostra una demo sul pannello LED: stati di LuZa e token, notifiche, animazioni, schermata musica.", "parameters": {"type": "object", "properties": {}}, "run": demo}, {"name": "ipixel_animazione", "description": "Mostra un'animazione sul pannello LED: plasma, matrix, stelle, cuore, equalizzatore, pacman; senza nome una sorpresa a caso (frase spiritosa, info o animazione).", "parameters": {"type": "object", "properties": {"nome": {"type": "string"}, "secondi": {"type": "number"}}}, "run": animazione}, {"name": "ipixel_scrivi", "description": "Scrive un testo sul pannello LED iPIXEL (scorre se è lungo) per alcuni secondi, poi torna all'orologio. colore: rosso, verde, blu, azzurro, giallo, arancione, viola, rosa, bianco, ciano.", "parameters": {"type": "object", "properties": {"testo": {"type": "string"}, "colore": {"type": "string"}, "secondi": {"type": "number"}}, "required": ["testo"]}, "run": scrivi}, {"name": "ipixel_immagine", "description": "Mostra un'immagine (percorso di un file) ridimensionata sul pannello LED.", "parameters": {"type": "object", "properties": {"percorso": {"type": "string"}, "secondi": {"type": "number"}}, "required": ["percorso"]}, "run": immagine}, {"name": "ipixel_luminosita", "description": "Imposta la luminosità del pannello LED (1-100).", "parameters": {"type": "object", "properties": {"livello": {"type": "integer"}}, "required": ["livello"]}, "run": luminosita}, {"name": "ipixel_accendi", "description": "Accende o spegne il pannello LED (acceso=true/false).", "parameters": {"type": "object", "properties": {"acceso": {"type": "boolean"}}}, "run": accendi}, {"name": "ipixel_orologio", "description": "Riporta il pannello LED all'orologio.", "parameters": {"type": "object", "properties": {}}, "run": orologio}, {"name": "ipixel_stato", "description": "Dice se il pannello LED è collegato e la sua risoluzione.", "parameters": {"type": "object", "properties": {}}, "run": stato}, ]