add socket management

This commit is contained in:
Nick
2025-10-27 19:51:03 +01:00
parent 20887ee5a1
commit e5951517f2

View File

@@ -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)
with TF5AIAgent(args.host, args.port) as agent:
if args.refresh_cache:
agent.controller.refresh_cache()
# 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()
if args.message:
print(f"🤖 Risposta: {agent.chat(args.message)}")
else:
agent.interactive_mode()
except Exception as e:
print(f"❌ Errore fatale: {e}")