166 lines
6.2 KiB
Python
166 lines
6.2 KiB
Python
"""
|
|
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
|