From e5951517f2e2060ada0f007d77c010e2a5af6aff Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 27 Oct 2025 19:51:03 +0100 Subject: [PATCH] add socket management --- mixer_agent.py | 110 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 28 deletions(-) diff --git a/mixer_agent.py b/mixer_agent.py index c6d800b..64ac266 100644 --- a/mixer_agent.py +++ b/mixer_agent.py @@ -30,14 +30,74 @@ CACHE_DURATION = 3600 # 60 minuti in secondi class TF5MixerController: - """Controller per il mixer Yamaha TF5 con sistema di caching.""" - def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT): self.host = host self.port = port + self.socket = None self._ensure_cache_dir() self._cache = self._load_cache() + def _connect(self): + """Stabilisce la connessione se non già connesso.""" + if self.socket is None: + print('Inizializzazione socket...') + try: + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.settimeout(5) + self.socket.connect((self.host, self.port)) + except socket.error as e: + self.socket = None + raise ConnectionError(f"Impossibile connettersi al mixer: {e}") + + def _disconnect(self): + """Chiude la connessione.""" + if self.socket: + print('Chiusura socket...') + try: + self.socket.close() + print('Socket chiuso!') + except: + print('Errore durante chiusura socket!') + pass + finally: + self.socket = None + + def _send_command(self, command: str) -> str: + """Invia un comando al mixer e restituisce la risposta.""" + max_retries = 2 + + for attempt in range(max_retries): + try: + print(f'Tentativo di connessione {attempt} per {command}') + self._connect() + self.socket.sendall((command + '\n').encode('utf-8')) + response = self.socket.recv(4096) + decoded = response.decode('utf-8', errors='ignore').strip() + print(f'Risposta {decoded}') + return decoded + + except socket.error as e: + print(f'Errore di connessione dopo {max_retries} tentativi: {e}') + self._disconnect() # Forza riconnessione al prossimo tentativo + + if attempt < max_retries - 1: + time.sleep(0.1) + continue + else: + return f"Errore di connessione dopo {max_retries} tentativi: {e}" + + def close(self): + """Chiude la connessione (da chiamare alla fine).""" + self._disconnect() + + def __enter__(self): + """Context manager entry.""" + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Context manager exit.""" + self.close() + def _ensure_cache_dir(self): """Crea la directory di cache se non esiste.""" CACHE_DIR.mkdir(parents=True, exist_ok=True) @@ -67,19 +127,6 @@ class TF5MixerController: cache_age = time.time() - self._cache.get("timestamp", 0) return cache_age < CACHE_DURATION - def _send_command(self, command: str) -> str: - """Invia un comando al mixer e restituisce la risposta.""" - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(5) - s.connect((self.host, self.port)) - s.sendall((command + '\n').encode('utf-8')) - response = s.recv(4096) - s.close() - return response.decode('utf-8', errors='ignore').strip() - except socket.error as e: - return f"Errore di connessione: {e}" - def _parse_name(self, response: str) -> str: """Estrae il nome tra virgolette dalla risposta.""" try: @@ -540,6 +587,18 @@ Esempi di comandi che puoi gestire: - "Aggiorna i dati dal mixer" (refresh_cache) """ + def __enter__(self): + """Context manager entry.""" + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Context manager exit.""" + self.controller.close() + + def close(self): + """Chiude le connessioni.""" + self.controller.close() + def chat(self, user_message: str) -> str: """Invia un messaggio all'agente e riceve la risposta. @@ -631,19 +690,14 @@ def main(): sys.exit(1) try: - agent = TF5AIAgent(args.host, args.port) - - # Refresh cache se richiesto - if args.refresh_cache: - agent.controller.refresh_cache() - - if args.message: - # Modalità singolo comando - print(f"🎛️ Comando: {args.message}") - print(f"\n🤖 Risposta: {agent.chat(args.message)}") - else: - # Modalità interattiva - agent.interactive_mode() + with TF5AIAgent(args.host, args.port) as agent: + if args.refresh_cache: + agent.controller.refresh_cache() + + if args.message: + print(f"🤖 Risposta: {agent.chat(args.message)}") + else: + agent.interactive_mode() except Exception as e: print(f"❌ Errore fatale: {e}")