sistemate alcune funzioni di contorno e rivista l'interfaccia di debug

This commit is contained in:
VALLONGOL 2025-10-20 15:39:08 +02:00
parent f23c522f60
commit c69de401e1
2 changed files with 87 additions and 16 deletions

View File

@ -287,9 +287,9 @@ class SfpTransport:
if frag == 0: if frag == 0:
self._cleanup_lingering_transactions(flow, tid) self._cleanup_lingering_transactions(flow, tid)
logger.debug( #logger.debug(
f"New transaction started for key={key}. Total size: {total_size} bytes." # f"New transaction started for key={key}. Total size: {total_size} bytes."
) #)
self._fragments[key] = {} self._fragments[key] = {}
try: try:
self._buffers[key] = bytearray(total_size) self._buffers[key] = bytearray(total_size)
@ -321,9 +321,9 @@ class SfpTransport:
] ]
if len(self._fragments[key]) == total_frags: if len(self._fragments[key]) == total_frags:
logger.debug( #logger.debug(
f"Transaction complete for key={key}. Handing off to application layer." # f"Transaction complete for key={key}. Handing off to application layer."
) #)
completed_payload = self._buffers.pop(key) completed_payload = self._buffers.pop(key)
self._fragments.pop(key) self._fragments.pop(key)

View File

@ -1,3 +1,4 @@
from target_simulator.gui.ppi_display import PPIDisplay
# target_simulator/gui/sfp_debug_window.py # target_simulator/gui/sfp_debug_window.py
""" """
Provides a Toplevel window for debugging the SFP transport layer. Provides a Toplevel window for debugging the SFP transport layer.
@ -14,6 +15,7 @@ import datetime
import os import os
import ctypes import ctypes
import time import time
import math
from typing import Dict, Callable, Optional, Any from typing import Dict, Callable, Optional, Any
import socket import socket
@ -69,6 +71,7 @@ class SfpDebugWindow(tk.Toplevel):
self.payload_router = DebugPayloadRouter() self.payload_router = DebugPayloadRouter()
self.sfp_transport: Optional[SfpTransport] = None self.sfp_transport: Optional[SfpTransport] = None
self.image_area_size = 150 self.image_area_size = 150
self._ppi_visible = False
# --- TK Variables --- # --- TK Variables ---
self.ip_var = tk.StringVar(value="127.0.0.1") self.ip_var = tk.StringVar(value="127.0.0.1")
@ -146,7 +149,7 @@ class SfpDebugWindow(tk.Toplevel):
self._create_target_sender_widgets(target_sender_frame) self._create_target_sender_widgets(target_sender_frame)
# --- Script Sender Frame (optional, can be removed if not needed) --- # --- Script Sender Frame (optional, can be removed if not needed) ---
script_frame = ttk.Frame(top_controls_frame) script_frame = ttk.LabelFrame(top_controls_frame, text="Script to send")
script_frame.pack(side=tk.TOP, fill=tk.X, pady=(0, 5)) script_frame.pack(side=tk.TOP, fill=tk.X, pady=(0, 5))
self._create_script_sender_widgets(script_frame) self._create_script_sender_widgets(script_frame)
@ -155,6 +158,54 @@ class SfpDebugWindow(tk.Toplevel):
self.notebook.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) self.notebook.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
self._create_notebook_tabs() self._create_notebook_tabs()
# (PPI widget is created inside the RIS tab right pane; see _create_notebook_tabs)
def _toggle_ppi(self):
# Swap RIS table and RIS PPI container
try:
if self._ppi_visible:
# show table, hide ppi
self.ris_ppi_container.pack_forget()
self.ris_table_container.pack(fill=tk.BOTH, expand=True)
self._ppi_visible = False
self.ppi_toggle_btn.config(text="Show PPI Map")
else:
# hide table, show ppi
self.ris_table_container.pack_forget()
self.ris_ppi_container.pack(fill=tk.BOTH, expand=True)
self._ppi_visible = True
self.ppi_toggle_btn.config(text="Hide PPI Map")
except Exception:
# Fallback: if containers are missing, do nothing
self.logger.exception("Toggle PPI failed")
def update_ppi_targets(self, targets):
if self._ppi_visible:
try:
self.ris_ppi_widget.update_targets(targets)
except Exception:
self.logger.exception("Failed to update RIS PPI targets")
def on_ris_status_update(self, ris_status_payload):
# Convert RIS targets to Target objects (minimal, for display)
targets = []
for i in range(getattr(ris_status_payload.tgt, 'tgt', []).__len__()):
ris_tgt = ris_status_payload.tgt.tgt[i]
# Only show if valid/active (customize as needed)
if getattr(ris_tgt, 'flags', 0) & 1:
t = Target(
target_id=i,
trajectory=[],
active=True,
traceable=True,
)
t.current_range_nm = (ris_tgt.x ** 2 + ris_tgt.y ** 2) ** 0.5 / 6076.12
t.current_azimuth_deg = math.degrees(math.atan2(ris_tgt.x, ris_tgt.y))
t.current_altitude_ft = ris_tgt.z
t.current_heading_deg = getattr(ris_tgt, 'heading', 0.0)
targets.append(t)
self.update_ppi_targets(targets)
def _create_connection_widgets(self, parent): def _create_connection_widgets(self, parent):
ttk.Label(parent, text="IP:").pack(side=tk.LEFT, padx=(4, 2)) ttk.Label(parent, text="IP:").pack(side=tk.LEFT, padx=(4, 2))
ttk.Entry(parent, textvariable=self.ip_var, width=18).pack( ttk.Entry(parent, textvariable=self.ip_var, width=18).pack(
@ -181,11 +232,8 @@ class SfpDebugWindow(tk.Toplevel):
# Quick commands frame # Quick commands frame
quick_frame = ttk.Frame(parent) quick_frame = ttk.Frame(parent)
quick_frame.pack(side=tk.RIGHT) quick_frame.pack(side=tk.RIGHT)
# Always prefix commands with '$' to satisfy server's mex parser # Always prefix commands with '$' to satisfy server's mex parser
ttk.Button(quick_frame, text="tgtreset", command=lambda: self._on_send_simple_command(command_builder.build_tgtreset())).pack(side=tk.LEFT, padx=2) # Quick command buttons moved to the Simple Target Sender area
ttk.Button(quick_frame, text="pause", command=lambda: self._on_send_simple_command(command_builder.build_pause())).pack(side=tk.LEFT, padx=2)
ttk.Button(quick_frame, text="continue", command=lambda: self._on_send_simple_command(command_builder.build_continue())).pack(side=tk.LEFT, padx=2)
ttk.Button(quick_frame, text="tgtset (cur)", command=lambda: self._on_send_tgtset()).pack(side=tk.LEFT, padx=6)
def _create_target_sender_widgets(self, parent): def _create_target_sender_widgets(self, parent):
grid = ttk.Frame(parent, padding=5) grid = ttk.Frame(parent, padding=5)
@ -249,6 +297,17 @@ class SfpDebugWindow(tk.Toplevel):
) )
send_button.pack(side=tk.LEFT, padx=(10, 0)) send_button.pack(side=tk.LEFT, padx=(10, 0))
# --- Quick command buttons (moved here from connection frame) ---
quick_cmd_frame = ttk.Frame(parent)
quick_cmd_frame.pack(fill=tk.X, pady=(6, 0))
ttk.Button(quick_cmd_frame, text="tgtreset", command=lambda: self._on_send_simple_command(command_builder.build_tgtreset())).pack(side=tk.LEFT, padx=4)
ttk.Button(quick_cmd_frame, text="pause", command=lambda: self._on_send_simple_command(command_builder.build_pause())).pack(side=tk.LEFT, padx=4)
ttk.Button(quick_cmd_frame, text="continue", command=lambda: self._on_send_simple_command(command_builder.build_continue())).pack(side=tk.LEFT, padx=4)
ttk.Button(quick_cmd_frame, text="tgtset (cur)", command=lambda: self._on_send_tgtset()).pack(side=tk.LEFT, padx=8)
# PPI toggle button (moved here)
self.ppi_toggle_btn = ttk.Button(quick_cmd_frame, text="Show PPI Map", command=self._toggle_ppi)
self.ppi_toggle_btn.pack(side=tk.RIGHT, padx=4)
def _create_script_sender_widgets(self, parent): def _create_script_sender_widgets(self, parent):
ttk.Label(parent, text="Script to send:").pack(side=tk.LEFT, padx=(5, 2)) ttk.Label(parent, text="Script to send:").pack(side=tk.LEFT, padx=(5, 2))
ttk.Entry(parent, textvariable=self.script_var, width=60).pack( ttk.Entry(parent, textvariable=self.script_var, width=60).pack(
@ -285,8 +344,12 @@ class SfpDebugWindow(tk.Toplevel):
self.scenario_tree.pack(fill=tk.BOTH, expand=True) self.scenario_tree.pack(fill=tk.BOTH, expand=True)
paned.add(left, weight=1) paned.add(left, weight=1)
right = ttk.Frame(paned) right = ttk.Frame(paned)
# Containers: one for the numeric table, one for the PPI (swapable)
self.ris_table_container = ttk.Frame(right)
self.ris_ppi_container = ttk.Frame(right)
cols = ("idx", "flags", "heading", "x", "y", "z") cols = ("idx", "flags", "heading", "x", "y", "z")
self.ris_tree = ttk.Treeview(right, columns=cols, show="headings", height=12) self.ris_tree = ttk.Treeview(self.ris_table_container, columns=cols, show="headings", height=12)
for c, txt in zip(cols, ("#", "flags", "heading", "x", "y", "z")): for c, txt in zip(cols, ("#", "flags", "heading", "x", "y", "z")):
self.ris_tree.heading(c, text=txt) self.ris_tree.heading(c, text=txt)
self.ris_tree.column(c, width=70, anchor="center") self.ris_tree.column(c, width=70, anchor="center")
@ -299,7 +362,15 @@ class SfpDebugWindow(tk.Toplevel):
except Exception: except Exception:
pass pass
self.ris_tree.pack(fill=tk.BOTH, expand=True) self.ris_tree.pack(fill=tk.BOTH, expand=True)
# Initially show table container, keep ppi container ready (hidden)
self.ris_table_container.pack(fill=tk.BOTH, expand=True)
paned.add(right, weight=2) paned.add(right, weight=2)
# Create PPI widget inside ris_ppi_container but keep it hidden
try:
self.ris_ppi_widget = PPIDisplay(self.ris_ppi_container, max_range_nm=100)
self.ris_ppi_widget.pack(fill=tk.BOTH, expand=True)
except Exception:
self.ris_ppi_widget = None
btn_frame = ttk.Frame(ris_frame) btn_frame = ttk.Frame(ris_frame)
btn_frame.pack(fill=tk.X, padx=5, pady=(0, 5)) btn_frame.pack(fill=tk.X, padx=5, pady=(0, 5))
self.scenario_view_mode = tk.StringVar(value="simplified") self.scenario_view_mode = tk.StringVar(value="simplified")
@ -788,7 +859,7 @@ class SfpDebugWindow(tk.Toplevel):
minutes_full = (ad - degrees) * 60 minutes_full = (ad - degrees) * 60
minutes = int(minutes_full) minutes = int(minutes_full)
seconds = (minutes_full - minutes) * 60 seconds = (minutes_full - minutes) * 60
return f"{degrees}°{minutes}'{seconds:.2f}\" {direction}" return f"{degrees}°{minutes}'{seconds:.2f} {direction}"
scenario_rows = [] scenario_rows = []
for label, key, unit in order: for label, key, unit in order:
if key in scenario: if key in scenario:
@ -1184,7 +1255,7 @@ class SfpDebugWindow(tk.Toplevel):
import json import json
text = json.dumps(json.loads(payload.decode("utf-8")), indent=2) text = json.dumps(json.loads(payload.decode("utf-8")), indent=2)
except Exception as e: except Exception as e:
text = f"--- FAILED TO PARSE JSON ---\n{e}\n\n--- RAW HEX DUMP ---\n" text = f"--- FAILED TO PARSE JSON ---\n{e}\n\n--- RAW HEX DUMP ---"
text += self._format_hex_dump(payload) text += self._format_hex_dump(payload)
widget.config(state=tk.NORMAL) widget.config(state=tk.NORMAL)
widget.delete("1.0", tk.END) widget.delete("1.0", tk.END)