add socket management
This commit is contained in:
108
mixer_agent.py
108
mixer_agent.py
@@ -30,14 +30,74 @@ CACHE_DURATION = 3600 # 60 minuti in secondi
|
|||||||
|
|
||||||
|
|
||||||
class TF5MixerController:
|
class TF5MixerController:
|
||||||
"""Controller per il mixer Yamaha TF5 con sistema di caching."""
|
|
||||||
|
|
||||||
def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT):
|
def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT):
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
|
self.socket = None
|
||||||
self._ensure_cache_dir()
|
self._ensure_cache_dir()
|
||||||
self._cache = self._load_cache()
|
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):
|
def _ensure_cache_dir(self):
|
||||||
"""Crea la directory di cache se non esiste."""
|
"""Crea la directory di cache se non esiste."""
|
||||||
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
@@ -67,19 +127,6 @@ class TF5MixerController:
|
|||||||
cache_age = time.time() - self._cache.get("timestamp", 0)
|
cache_age = time.time() - self._cache.get("timestamp", 0)
|
||||||
return cache_age < CACHE_DURATION
|
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:
|
def _parse_name(self, response: str) -> str:
|
||||||
"""Estrae il nome tra virgolette dalla risposta."""
|
"""Estrae il nome tra virgolette dalla risposta."""
|
||||||
try:
|
try:
|
||||||
@@ -540,6 +587,18 @@ Esempi di comandi che puoi gestire:
|
|||||||
- "Aggiorna i dati dal mixer" (refresh_cache)
|
- "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:
|
def chat(self, user_message: str) -> str:
|
||||||
"""Invia un messaggio all'agente e riceve la risposta.
|
"""Invia un messaggio all'agente e riceve la risposta.
|
||||||
|
|
||||||
@@ -631,19 +690,14 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
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.message:
|
||||||
if args.refresh_cache:
|
print(f"🤖 Risposta: {agent.chat(args.message)}")
|
||||||
agent.controller.refresh_cache()
|
else:
|
||||||
|
agent.interactive_mode()
|
||||||
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()
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Errore fatale: {e}")
|
print(f"❌ Errore fatale: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user