Separando los logs

This commit is contained in:
Miguel 2025-05-31 00:05:21 +02:00
parent 835bfc0383
commit d7d52b2565
2 changed files with 98 additions and 60 deletions

View File

@ -186,7 +186,9 @@ class MaselliApp:
def create_graphs(self):
"""Crea los gráficos para simulador y trace"""
# Gráfico del simulador
sim_graph_frame = self.simulator_tab.get_graph_frame()
# get_graph_frame() ahora devuelve el contenedor LabelFrame donde debe ir el canvas.
# Este contenedor ya está posicionado por SimulatorTab.create_widgets().
sim_graph_canvas_parent = self.simulator_tab.get_graph_frame()
self.sim_fig = Figure(figsize=(8, 3.5), dpi=100)
self.sim_ax1 = self.sim_fig.add_subplot(111)
@ -202,9 +204,13 @@ class MaselliApp:
self.sim_line_brix, = self.sim_ax1.plot([], [], 'b-', label='Brix', linewidth=2)
self.sim_line_ma, = self.sim_ax2.plot([], [], 'r-', label='mA', linewidth=2)
self.sim_canvas = FigureCanvasTkAgg(self.sim_fig, master=sim_graph_frame)
self.sim_canvas = FigureCanvasTkAgg(self.sim_fig, master=sim_graph_canvas_parent) # sim_graph_canvas_parent es un LabelFrame
self.sim_canvas.draw()
self.sim_canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
sim_canvas_widget = self.sim_canvas.get_tk_widget()
sim_canvas_widget.grid(row=0, column=0, sticky="nsew", padx=5, pady=5)
# Configurar el LabelFrame (sim_graph_canvas_parent) para que el canvas (su hijo) se expanda
sim_graph_canvas_parent.rowconfigure(0, weight=1)
sim_graph_canvas_parent.columnconfigure(0, weight=1)
# Gráfico del trace (ahora con doble eje Y)
trace_graph_frame = self.trace_tab.get_graph_frame()
@ -223,9 +229,13 @@ class MaselliApp:
self.trace_line_brix, = self.trace_ax1.plot([], [], 'b-', label='Brix', linewidth=2, marker='o', markersize=4)
self.trace_line_ma, = self.trace_ax2.plot([], [], 'r-', label='mA', linewidth=2, marker='s', markersize=3)
self.trace_canvas = FigureCanvasTkAgg(self.trace_fig, master=trace_graph_frame)
self.trace_canvas = FigureCanvasTkAgg(self.trace_fig, master=trace_graph_frame) # trace_graph_frame es un LabelFrame
self.trace_canvas.draw()
self.trace_canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
trace_canvas_widget = self.trace_canvas.get_tk_widget()
trace_canvas_widget.grid(row=0, column=0, sticky="nsew", padx=5, pady=5)
# Configurar el LabelFrame (trace_graph_frame) para que el canvas (su hijo) se expanda
trace_graph_frame.rowconfigure(0, weight=1)
trace_graph_frame.columnconfigure(0, weight=1)
def update_sim_graph(self, frame=None):
"""Actualiza el gráfico del simulador"""

View File

@ -64,8 +64,9 @@ class SimulatorTab:
self.random_error_interval_var = tk.StringVar(value=initial_config.get('random_error_interval', '10.0'))
self.error_details_for_replacement = None # (message_bytes, log_suffix, error_type_str)
self.actual_graph_frame_container = None # Inicializar ANTES de create_widgets
self.create_widgets()
# La línea anterior que asignaba None aquí ha sido eliminada.
def create_widgets(self):
"""Crea los widgets del tab simulador"""
# Frame de configuración del simulador
@ -137,12 +138,15 @@ class SimulatorTab:
self.stop_button = ttk.Button(controls_frame, text="Detener", command=self.stop_simulation, state=tk.DISABLED)
self.stop_button.pack(side=tk.LEFT, padx=5)
self.clear_comm_log_button = ttk.Button(controls_frame, text="Limpiar Log Com.", command=self.clear_comm_log)
self.clear_comm_log_button.pack(side=tk.LEFT, padx=5)
self.clear_graph_button = ttk.Button(controls_frame, text="Limpiar Gráfico", command=self.clear_graph)
self.clear_graph_button.pack(side=tk.LEFT, padx=5)
# Display Frame
display_frame = ttk.LabelFrame(self.frame, text="Valores Actuales")
display_frame.grid(row=1, column=1, padx=10, pady=5, sticky="ew")
display_frame.grid(row=1, column=1, padx=10, pady=5, sticky="nsew")
ttk.Label(display_frame, text="Brix:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
# self.current_brix_var inicializada en __init__
@ -159,12 +163,33 @@ class SimulatorTab:
ttk.Label(display_frame, textvariable=self.current_voltage_var,
font=("Courier", 14, "bold")).grid(row=2, column=1, padx=5, pady=5, sticky="w")
# Log Frame
log_frame = ttk.LabelFrame(self.frame, text="Log de Comunicación")
log_frame.grid(row=2, column=0, columnspan=2, padx=10, pady=5, sticky="nsew")
# Event Log Frame (antes era el log principal)
event_log_frame = ttk.LabelFrame(self.frame, text="Log de Eventos")
event_log_frame.grid(row=2, column=0, columnspan=2, padx=10, pady=5, sticky="nsew")
self.log_text = scrolledtext.ScrolledText(log_frame, height=8, width=70, wrap=tk.WORD, state=tk.DISABLED)
self.log_text.pack(padx=5, pady=5, fill=tk.BOTH, expand=True)
self.event_log_text = scrolledtext.ScrolledText(event_log_frame, height=8, width=70, wrap=tk.WORD, state=tk.DISABLED)
self.event_log_text.pack(padx=5, pady=5, fill=tk.BOTH, expand=True)
# --- Frame para Comunicación y Gráfico ---
comm_and_graph_parent_frame = ttk.Frame(self.frame)
comm_and_graph_parent_frame.grid(row=3, column=0, columnspan=2, padx=10, pady=5, sticky="nsew")
comm_and_graph_parent_frame.columnconfigure(0, weight=1) # Comm log
comm_and_graph_parent_frame.columnconfigure(1, weight=1) # Graph
comm_and_graph_parent_frame.rowconfigure(0, weight=1) # Ambos toman la altura completa de esta fila
# Comm Log Frame (Nuevo)
comm_log_frame = ttk.LabelFrame(comm_and_graph_parent_frame, text="Log de Comunicación (Simulador)")
comm_log_frame.grid(row=0, column=0, padx=(0, 5), pady=0, sticky="nsew")
comm_log_frame.rowconfigure(0, weight=1)
comm_log_frame.columnconfigure(0, weight=1)
self.comm_log_text = scrolledtext.ScrolledText(comm_log_frame, height=10, width=70, wrap=tk.WORD, state=tk.DISABLED)
self.comm_log_text.pack(padx=5, pady=5, fill=tk.BOTH, expand=True)
# Graph Frame Container (el gráfico se insertará aquí por MaselliApp)
# self.get_graph_frame() ahora devuelve este contenedor.
self.actual_graph_frame_container = ttk.LabelFrame(comm_and_graph_parent_frame, text="Gráfico Simulador")
self.actual_graph_frame_container.grid(row=0, column=1, padx=(5, 0), pady=0, sticky="nsew")
# --- Frame para Simulación de Errores ---
self._setup_error_simulation_ui() # Se añade al final de create_widgets
@ -172,18 +197,16 @@ class SimulatorTab:
# Configurar pesos
self.frame.columnconfigure(0, weight=1)
self.frame.columnconfigure(1, weight=1)
self.frame.rowconfigure(2, weight=1) # Log frame
self.frame.rowconfigure(2, weight=1) # Event log frame
self.frame.rowconfigure(3, weight=3) # Comm and Graph parent frame (más altura)
self.frame.rowconfigure(4, weight=0) # Error frame no se expande tanto
# Inicializar estado
self.on_function_type_change()
def get_graph_frame(self):
"""Crea y retorna el frame para el gráfico"""
graph_frame = ttk.LabelFrame(self.frame, text="Gráfico Simulador")
graph_frame.grid(row=3, column=0, columnspan=2, padx=10, pady=5, sticky="nsew")
# El rowconfigure para el gráfico se hace aquí, y el de errores abajo
self.frame.rowconfigure(3, weight=1) # Graph frame (se mueve una fila abajo)
return graph_frame
"""Retorna el frame contenedor donde se debe dibujar el gráfico del simulador."""
return self.actual_graph_frame_container
def _setup_error_simulation_ui(self):
"""Crea los controles para la simulación de errores."""
@ -293,7 +316,7 @@ class SimulatorTab:
min_b = float(self.shared_config['min_brix_map_var'].get())
max_b = float(self.shared_config['max_brix_map_var'].get())
base_ma_value = ProtocolHandler.scale_to_ma(manual_val, min_b, max_b)
elif input_type == "mA":
elif input_type == "mA": # noqa: E721
base_ma_value = manual_val
elif input_type == "Voltaje":
base_ma_value = ProtocolHandler.voltage_to_ma(manual_val)
@ -354,10 +377,10 @@ class SimulatorTab:
default_val = min_val + (max_val - min_val) / 4
except (ValueError, KeyError, TypeError):
min_val, max_val = 0.0, 80.0
default_val = 10.0
default_val = 10.0 # noqa: F841
label_text = "Valor Brix:"
precision = 2
elif input_type == "mA":
elif input_type == "mA": # noqa: E721
min_val, max_val = 0.0, 20.0
default_val = 12.0
label_text = "Valor mA:"
@ -388,7 +411,7 @@ class SimulatorTab:
value = float(value_str)
input_type = self.manual_input_type_var.get()
precision = 2
if input_type == "Brix": precision = 2
if input_type == "Brix": precision = 2 # noqa: E701
elif input_type == "mA": precision = 3
elif input_type == "Voltaje": precision = 2
self.manual_value_var.set(f"{value:.{precision}f}")
@ -405,7 +428,7 @@ class SimulatorTab:
max_val = float(self.shared_config['max_brix_map_var'].get())
if min_val >= max_val: min_val, max_val = 0.0, 80.0
precision = 2
elif input_type == "mA": min_val, max_val, precision = 0.0, 20.0, 3
elif input_type == "mA": min_val, max_val, precision = 0.0, 20.0, 3 # noqa: E701
elif input_type == "Voltaje": min_val, max_val, precision = 0.0, 10.0, 2
value = max(min_val, min(max_val, value)) # Clampear al rango
@ -464,9 +487,9 @@ class SimulatorTab:
_, listening_details = self.connection_manager.open_connection(conn_type, conn_params)
if conn_type == "TCP-Server":
Utils.log_message(self.log_text, f"{listening_details} para simulación.")
Utils.log_message(self.comm_log_text, f"{listening_details} para simulación.")
elif conn_type != "TCP-Server": # Para otros tipos, el mensaje genérico
Utils.log_message(self.log_text, f"Conexión {conn_type} abierta para simulación.")
Utils.log_message(self.comm_log_text, f"Conexión {conn_type} abierta para simulación.")
except Exception as e:
messagebox.showerror("Error de Conexión", str(e))
return
@ -482,8 +505,8 @@ class SimulatorTab:
self.shared_config['client_connected_var'].set("Esperando...")
self.simulation_thread = threading.Thread(target=self.run_simulation, daemon=True)
self.simulation_thread.start()
Utils.log_message(self.log_text, "Simulación iniciada.")
self.simulation_thread.start() # noqa: E701
Utils.log_message(self.event_log_text, "Simulación iniciada.")
def stop_simulation(self):
"""Detiene la simulación"""
@ -504,14 +527,14 @@ class SimulatorTab:
self.simulation_thread.join(timeout=2.0)
self.connection_manager.close_connection()
Utils.log_message(self.log_text, "Conexión cerrada.")
Utils.log_message(self.comm_log_text, "Conexión cerrada.")
self._set_entries_state(tk.NORMAL)
self.on_function_type_change() # Re-evaluar estado de controles manuales
if self.connection_manager.connection_type == "TCP-Server": # Limpiar info del cliente
self.shared_config['client_connected_var'].set("Ninguno")
Utils.log_message(self.log_text, "Simulación detenida.")
Utils.log_message(self.event_log_text, "Simulación detenida.")
self.current_brix_var.set("---")
self.current_ma_var.set("--.-- mA")
self.current_voltage_var.set("-.-- V")
@ -561,7 +584,7 @@ class SimulatorTab:
try:
manual_numeric_value = float(self.manual_value_var.get())
except ValueError:
Utils.log_message(self.log_text, f"Valor manual inválido: '{self.manual_value_var.get()}'. Usando valor por defecto.")
Utils.log_message(self.event_log_text, f"Valor manual inválido: '{self.manual_value_var.get()}'. Usando valor por defecto.")
if manual_input_type == "Brix": manual_numeric_value = min_brix_map
elif manual_input_type == "mA": manual_numeric_value = 4.0
elif manual_input_type == "Voltaje": manual_numeric_value = ProtocolHandler.ma_to_voltage(4.0)
@ -641,10 +664,10 @@ class SimulatorTab:
if not self.connection_manager.is_client_connected():
if not hasattr(self, '_waiting_for_client_logged') or not self._waiting_for_client_logged:
port_to_log = self.shared_config['config_manager'].get_connection_params(current_config_values)['port']
Utils.log_message(self.log_text, f"TCP Server: Esperando cliente en puerto {port_to_log}...")
Utils.log_message(self.comm_log_text, f"TCP Server: Esperando cliente en puerto {port_to_log}...")
self._waiting_for_client_logged = True
if self.connection_manager.accept_client(timeout=0.05):
Utils.log_message(self.log_text, f"TCP Server: Cliente conectado desde {self.connection_manager.client_address}")
Utils.log_message(self.comm_log_text, f"TCP Server: Cliente conectado desde {self.connection_manager.client_address}")
client_info = f"{self.connection_manager.client_address[0]}:{self.connection_manager.client_address[1]}"
self.shared_config['client_connected_var'].set(client_info)
self._waiting_for_client_logged = False
@ -654,41 +677,41 @@ class SimulatorTab:
log_content = ProtocolHandler.format_for_display(message_to_send, hex_non_printable=True)
if actual_error_type_sent != "Normal" and log_prefix_for_send.startswith("Error Sim (Reemplazo Programado)"):
Utils.log_message(self.log_text, f"{log_prefix_for_send}: Trama '{actual_error_type_sent}'{log_suffix_for_send} -> {log_content}")
Utils.log_message(self.comm_log_text, f"{log_prefix_for_send}: Trama '{actual_error_type_sent}'{log_suffix_for_send} -> {log_content}")
else:
Utils.log_message(self.log_text, f"{log_prefix_for_send}: {log_content}")
Utils.log_message(self.comm_log_text, f"{log_prefix_for_send}: {log_content}")
self.connection_manager.send_data(message_to_send)
if conn_type != "TCP-Server": # No leer respuesta en modo servidor
response = self.connection_manager.read_response(timeout=0.1)
if response and response.strip():
Utils.log_message(self.log_text, f"Respuesta: {ProtocolHandler.format_for_display(response)}")
Utils.log_message(self.comm_log_text, f"Respuesta: {ProtocolHandler.format_for_display(response)}")
parsed = ProtocolHandler.parse_adam_message(response)
if parsed:
brix_resp = ProtocolHandler.ma_to_brix(parsed['ma'], min_brix_map, max_brix_map)
Utils.log_message(self.log_text,
Utils.log_message(self.comm_log_text,
f" -> Addr: {parsed['address']}, "
f"mA: {parsed['ma']:.3f}, "
f"Brix: {brix_resp:.3f}")
except self.connection_manager.ClientDisconnectedError:
Utils.log_message(self.log_text, "TCP Server: Cliente desconectado. Esperando nueva conexión.")
Utils.log_message(self.comm_log_text, "TCP Server: Cliente desconectado. Esperando nueva conexión.")
if conn_type == "TCP-Server":
self.shared_config['client_connected_var'].set("Esperando...")
self._waiting_for_client_logged = False
except Exception as e:
Utils.log_message(self.log_text, f"Error en comunicación ({conn_type}): {e}")
Utils.log_message(self.comm_log_text, f"Error en comunicación ({conn_type}): {e}")
self.frame.after(0, self.stop_simulation_error)
break
elif actual_error_type_sent == "Trama Faltante (Omitir Envío)" and log_prefix_for_send.startswith("Error Sim (Reemplazo Programado)"):
# Loguear que se omitió una trama debido al reemplazo por "Trama Faltante"
Utils.log_message(self.log_text, f"{log_prefix_for_send}: Simulación de '{actual_error_type_sent}'{log_suffix_for_send}. No se envió trama.")
Utils.log_message(self.comm_log_text, f"{log_prefix_for_send}: Simulación de '{actual_error_type_sent}'{log_suffix_for_send}. No se envió trama.")
self.simulation_step += 1
time.sleep(sample_period)
except Exception as e: # Catches errors in parameter fetching or main loop logic
Utils.log_message(self.log_text, f"Error en simulación: {e}")
Utils.log_message(self.event_log_text, f"Error en simulación: {e}")
if self.simulating: # Ensure stop is called only if an error occurs while simulating
self.frame.after(0, self.stop_simulation_error)
@ -736,7 +759,7 @@ class SimulatorTab:
message_bytes, _ = ProtocolHandler.create_adam_message_from_ma(adam_address, base_ma_value)
log_message_suffix = " (trama normal)"
else:
Utils.log_message(self.log_text, f"Error Sim: Tipo de error '{error_type}' desconocido.")
Utils.log_message(self.comm_log_text, f"Error Sim: Tipo de error '{error_type}' desconocido.")
return None, f" (tipo de error '{error_type}' desconocido)"
return message_bytes, log_message_suffix
@ -748,7 +771,7 @@ class SimulatorTab:
return
if not self.connection_manager.is_client_connected():
Utils.log_message(self.log_text, "Error Sim: No hay cliente conectado para enviar trama errónea.")
Utils.log_message(self.comm_log_text, "Error Sim: No hay cliente conectado para enviar trama errónea.")
# messagebox.showinfo("Sin Cliente", "No hay cliente conectado para enviar la trama errónea.")
# return # Permitir enviar aunque no haya cliente, el log lo indicará
@ -762,21 +785,21 @@ class SimulatorTab:
self.error_details_for_replacement = (message_bytes, log_suffix_from_gen, error_type)
self.next_frame_is_error_event.set()
if error_type == "Trama Faltante (Omitir Envío)":
Utils.log_message(self.log_text, f"Error Sim Manual: Programada OMISIÓN de trama '{error_type}'{log_suffix_from_gen} para reemplazo.")
Utils.log_message(self.comm_log_text, f"Error Sim Manual: Programada OMISIÓN de trama '{error_type}'{log_suffix_from_gen} para reemplazo.")
elif message_bytes:
Utils.log_message(self.log_text, f"Error Sim Manual: Programada trama '{error_type}'{log_suffix_from_gen} para reemplazo.")
Utils.log_message(self.comm_log_text, f"Error Sim Manual: Programada trama '{error_type}'{log_suffix_from_gen} para reemplazo.")
else: # Error en generación o tipo desconocido
Utils.log_message(self.log_text, f"Error Sim Manual: No se pudo programar trama '{error_type}'{log_suffix_from_gen} para reemplazo.")
Utils.log_message(self.comm_log_text, f"Error Sim Manual: No se pudo programar trama '{error_type}'{log_suffix_from_gen} para reemplazo.")
else:
# Enviar inmediatamente como trama adicional
if message_bytes:
try:
self.connection_manager.send_data(message_bytes)
Utils.log_message(self.log_text, f"Error Sim Manual (Adicional): Trama '{error_type}'{log_suffix_from_gen} -> {ProtocolHandler.format_for_display(message_bytes, hex_non_printable=True)}")
Utils.log_message(self.comm_log_text, f"Error Sim Manual (Adicional): Trama '{error_type}'{log_suffix_from_gen} -> {ProtocolHandler.format_for_display(message_bytes, hex_non_printable=True)}")
except Exception as e:
Utils.log_message(self.log_text, f"Error Sim Manual (Adicional): Fallo al enviar trama: {e}")
Utils.log_message(self.comm_log_text, f"Error Sim Manual (Adicional): Fallo al enviar trama: {e}")
elif error_type == "Trama Faltante (Omitir Envío)":
Utils.log_message(self.log_text, f"Error Sim Manual (Adicional): Simulación de '{error_type}'{log_suffix_from_gen}. No se envió trama adicional.")
Utils.log_message(self.comm_log_text, f"Error Sim Manual (Adicional): Simulación de '{error_type}'{log_suffix_from_gen}. No se envió trama adicional.")
# else: Ya logueado por generate_erroneous_message_logic si message_bytes es None y no es "Trama Faltante"
def toggle_random_errors(self):
@ -787,7 +810,7 @@ class SimulatorTab:
if self.random_error_var.get(): # Si el usuario intenta activar los errores aleatorios
if not can_actually_start_random_errors:
Utils.log_message(self.log_text, "Error Sim: Errores aleatorios solo en TCP-Server con simulación activa.")
Utils.log_message(self.event_log_text, "Error Sim: Errores aleatorios solo en TCP-Server con simulación activa.")
self.random_error_var.set(False) # Forzar a False ya que las condiciones no se cumplen
# El timer no se iniciará. update_error_controls_state() al final se encargará.
else: # Las condiciones se cumplen, iniciar el timer si no está ya activo
@ -811,7 +834,7 @@ class SimulatorTab:
self.random_error_timer.start()
else: # Si el usuario intenta desactivar los errores aleatorios (el checkbox ahora está desmarcado)
if self.random_error_timer and self.random_error_timer.is_alive():
Utils.log_message(self.log_text, "Error Sim: Deteniendo envío de errores aleatorios.")
Utils.log_message(self.event_log_text, "Error Sim: Deteniendo envío de errores aleatorios.")
self.random_error_timer_stop_event.set()
# No es necesario join aquí, se hará en stop_simulation o al cerrar.
@ -824,7 +847,7 @@ class SimulatorTab:
if not possible_error_types: return
current_interval = initial_interval_s
Utils.log_message(self.log_text, f"Error Sim: Hilo de errores aleatorios iniciado con intervalo {current_interval:.2f}s.")
Utils.log_message(self.event_log_text, f"Error Sim: Hilo de errores aleatorios iniciado con intervalo {current_interval:.2f}s.")
while not self.random_error_timer_stop_event.is_set():
if not (self.shared_config['connection_type_var'].get() == "TCP-Server" and self.simulating and self.connection_manager.is_client_connected()):
@ -840,29 +863,29 @@ class SimulatorTab:
self.error_details_for_replacement = (message_bytes, log_suffix, selected_random_error)
self.next_frame_is_error_event.set()
# El log de este envío se hará en run_simulation cuando efectivamente se envíe/omita
Utils.log_message(self.log_text, f"Error Sim Aleatorio: Programada trama '{selected_random_error}'{log_suffix} para reemplazo.")
Utils.log_message(self.comm_log_text, f"Error Sim Aleatorio: Programada trama '{selected_random_error}'{log_suffix} para reemplazo.")
else:
# Enviar el error inmediatamente, además de las tramas normales
if message_bytes:
try:
self.connection_manager.send_data(message_bytes)
Utils.log_message(self.log_text, f"Error Sim Aleatorio (Adicional): Trama '{selected_random_error}'{log_suffix} -> {ProtocolHandler.format_for_display(message_bytes, hex_non_printable=True)}")
Utils.log_message(self.comm_log_text, f"Error Sim Aleatorio (Adicional): Trama '{selected_random_error}'{log_suffix} -> {ProtocolHandler.format_for_display(message_bytes, hex_non_printable=True)}")
except Exception as e:
Utils.log_message(self.log_text, f"Error Sim Aleatorio (Adicional): Fallo al enviar: {e}")
Utils.log_message(self.comm_log_text, f"Error Sim Aleatorio (Adicional): Fallo al enviar: {e}")
elif selected_random_error == "Trama Faltante (Omitir Envío)":
Utils.log_message(self.log_text, f"Error Sim Aleatorio (Adicional): Simulación de '{selected_random_error}'{log_suffix}. No se envió trama adicional.")
Utils.log_message(self.comm_log_text, f"Error Sim Aleatorio (Adicional): Simulación de '{selected_random_error}'{log_suffix}. No se envió trama adicional.")
# Permitir que el intervalo se actualice dinámicamente
try:
new_interval = float(self.random_error_interval_var.get())
if new_interval > 0 and new_interval != current_interval:
current_interval = new_interval
Utils.log_message(self.log_text, f"Error Sim: Intervalo de errores aleatorios actualizado a {current_interval:.2f}s.")
Utils.log_message(self.event_log_text, f"Error Sim: Intervalo de errores aleatorios actualizado a {current_interval:.2f}s.")
except ValueError:
pass # Mantener el intervalo actual si el nuevo valor es inválido
self.random_error_timer_stop_event.wait(timeout=current_interval)
Utils.log_message(self.log_text, "Error Sim: Hilo de errores aleatorios detenido.")
Utils.log_message(self.event_log_text, "Error Sim: Hilo de errores aleatorios detenido.")
def add_data_point(self, brix_value, ma_value):
"""Agrega un punto de datos al gráfico"""
@ -877,12 +900,17 @@ class SimulatorTab:
def clear_graph(self):
"""Limpia los datos del gráfico"""
Utils.clear_graph_data(self.time_data, self.brix_data, self.ma_data)
self.start_time = time.time()
Utils.log_message(self.log_text, "Gráfico limpiado.")
self.start_time = time.time() # noqa: F841
Utils.log_message(self.event_log_text, "Gráfico del simulador limpiado.")
if hasattr(self, 'graph_update_callback'):
self.graph_update_callback()
def clear_comm_log(self):
"""Limpia el log de comunicación del simulador."""
Utils.clear_log_widget(self.comm_log_text)
Utils.log_message(self.event_log_text, "Log de comunicación del simulador limpiado.")
def _set_entries_state(self, state):
"""Habilita/deshabilita los controles durante la simulación"""
sim_specific_widgets = [