""" Gestor de conexiones para Serial, TCP y UDP """ import serial import socket import time class ConnectionManager: def __init__(self): self.connection = None self.connection_type = None self.dest_address = None # Para UDP def open_connection(self, conn_type, conn_params): """Abre una conexión según el tipo especificado""" try: if conn_type == "Serial": self.connection = serial.Serial( conn_params['port'], conn_params['baud'], timeout=1 ) self.connection_type = "Serial" elif conn_type == "TCP": sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5.0) sock.connect((conn_params['ip'], conn_params['port'])) self.connection = sock self.connection_type = "TCP" elif conn_type == "UDP": sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(1.0) self.dest_address = (conn_params['ip'], conn_params['port']) self.connection = sock self.connection_type = "UDP" return self.connection except Exception as e: raise Exception(f"Error al abrir conexión {conn_type}: {e}") def close_connection(self): """Cierra la conexión actual""" try: if self.connection_type == "Serial": if self.connection and self.connection.is_open: self.connection.close() elif self.connection_type in ["TCP", "UDP"]: if self.connection: self.connection.close() except Exception as e: print(f"Error al cerrar conexión: {e}") finally: self.connection = None self.connection_type = None self.dest_address = None def send_data(self, data): """Envía datos por la conexión actual""" if not self.connection: raise Exception("No hay conexión activa") try: if self.connection_type == "Serial": self.connection.write(data.encode('ascii')) elif self.connection_type == "TCP": self.connection.send(data.encode('ascii')) elif self.connection_type == "UDP": self.connection.sendto(data.encode('ascii'), self.dest_address) except Exception as e: raise Exception(f"Error al enviar datos: {e}") def read_response(self, timeout=0.5): """Intenta leer una respuesta del dispositivo""" if not self.connection: return None try: response = None if self.connection_type == "Serial": # Guardar timeout original original_timeout = self.connection.timeout self.connection.timeout = timeout # Esperar un poco para que llegue la respuesta time.sleep(0.05) # Leer todos los bytes disponibles response_bytes = b"" start_time = time.time() while (time.time() - start_time) < timeout: if self.connection.in_waiting > 0: response_bytes += self.connection.read(self.connection.in_waiting) # Si encontramos un terminador, salir if b'\r' in response_bytes or b'\n' in response_bytes: break else: time.sleep(0.01) if response_bytes: response = response_bytes.decode('ascii', errors='ignore') self.connection.timeout = original_timeout elif self.connection_type == "TCP": self.connection.settimeout(timeout) try: response = self.connection.recv(1024).decode('ascii', errors='ignore') except socket.timeout: pass elif self.connection_type == "UDP": self.connection.settimeout(timeout) try: response, addr = self.connection.recvfrom(1024) response = response.decode('ascii', errors='ignore') except socket.timeout: pass return response except Exception as e: print(f"Error al leer respuesta: {e}") return None def read_data_non_blocking(self): """Lee datos disponibles sin bloquear (para modo trace y netcom)""" if not self.connection: return None try: data = None if self.connection_type == "Serial": if self.connection.in_waiting > 0: data = self.connection.read(self.connection.in_waiting).decode('ascii', errors='ignore') elif self.connection_type == "TCP": self.connection.settimeout(0.1) try: data = self.connection.recv(1024).decode('ascii', errors='ignore') if not data: # Conexión cerrada return None except socket.timeout: pass elif self.connection_type == "UDP": self.connection.settimeout(0.1) try: data, addr = self.connection.recvfrom(1024) data = data.decode('ascii', errors='ignore') except socket.timeout: pass return data except Exception as e: print(f"Error al leer datos: {e}") return None def is_connected(self): """Verifica si hay una conexión activa""" if self.connection_type == "Serial": return self.connection and self.connection.is_open else: return self.connection is not None