sistemata la comunicazione via json, da sistemare quella mediante comando semplice tgtset/tgtinit

This commit is contained in:
VALLONGOL 2025-10-29 11:10:59 +01:00
parent fc1722d8eb
commit 3213d61e5b
5 changed files with 79 additions and 11 deletions

View File

@ -17,7 +17,7 @@
},
"sfp": {
"ip": "127.0.0.1",
"port": 60001,
"port": 60003,
"local_port": 60002,
"use_json_protocol": true
}

View File

@ -19,6 +19,7 @@ from target_simulator.utils.logger import get_logger
from target_simulator.gui.payload_router import DebugPayloadRouter
from target_simulator.analysis.simulation_state_hub import SimulationStateHub
from target_simulator.config import DEBUG_CONFIG
import json
class SFPCommunicator(CommunicatorInterface):
@ -219,6 +220,8 @@ class SFPCommunicator(CommunicatorInterface):
# --- JSON Protocol Logic for scenario initialization ---
self.logger.debug("Using JSON protocol for scenario initialization.")
json_command = command_builder.build_json_update(scenario.get_all_targets())
# Compact the JSON payload to a single-line string before saving/sending
json_command = self._compact_json_if_needed(json_command)
self._save_json_payload_to_temp(json_command, "sfp_scenario_init")
if not self._send_single_command(json_command):
@ -262,6 +265,8 @@ class SFPCommunicator(CommunicatorInterface):
# Expect a single command string which is the JSON payload
json_payload = commands[0]
# Compact JSON for live updates before saving/sending
json_payload = self._compact_json_if_needed(json_payload)
self._save_json_payload_to_temp(json_payload, "sfp_live_update")
return self._send_single_command(json_payload)
else:
@ -275,8 +280,41 @@ class SFPCommunicator(CommunicatorInterface):
def _send_single_command(self, command: str) -> bool:
if not self.transport or not self._destination:
return False
# As a final safeguard, compact JSON payloads here as well
try:
command = self._compact_json_if_needed(command)
except Exception:
pass
return self.transport.send_script_command(command, self._destination)
def _compact_json_if_needed(self, command: str) -> str:
"""If the command is a JSON document (starts with { or [), return a compact
single-line JSON string (no unnecessary spaces/newlines) with a trailing newline.
Otherwise return the original command unchanged.
"""
if not isinstance(command, str):
try:
command = str(command)
except Exception:
return command
s = command.strip()
if not s:
return command
if not (s.startswith("{") or s.startswith("[")):
return command
try:
obj = json.loads(s)
compact = json.dumps(obj, separators=(',', ':'))
if not compact.endswith("\n"):
compact += "\n"
return compact
except Exception:
# If parsing fails, return original command (avoid changing it)
return command
@staticmethod
def test_connection(config: Dict[str, Any]) -> bool:
local_port = config.get("local_port")

View File

@ -64,7 +64,7 @@ class ConnectionSettingsWindow(tk.Toplevel):
target_cfg.get("serial", {}).get("baudrate", 9600)
)
self.target_vars["sfp_ip"].set(target_sfp_cfg.get("ip", "127.0.0.1"))
self.target_vars["sfp_port"].set(target_sfp_cfg.get("port", 60001))
self.target_vars["sfp_port"].set(target_sfp_cfg.get("port", 60003))
self.target_vars["sfp_local_port"].set(target_sfp_cfg.get("local_port", 60002))
self.target_vars["sfp_use_json"].set(
target_sfp_cfg.get("use_json_protocol", False)
@ -93,7 +93,7 @@ class ConnectionSettingsWindow(tk.Toplevel):
lru_cfg.get("serial", {}).get("baudrate", 9600)
)
self.lru_vars["sfp_ip"].set(lru_sfp_cfg.get("ip", "127.0.0.1"))
self.lru_vars["sfp_port"].set(lru_sfp_cfg.get("port", 60001))
self.lru_vars["sfp_port"].set(lru_sfp_cfg.get("port", 60003))
self.lru_vars["sfp_local_port"].set(lru_sfp_cfg.get("local_port", 60002))
self.lru_vars["sfp_use_json"].set(lru_sfp_cfg.get("use_json_protocol", False))
# Select the correct notebook tab for lru

View File

@ -76,7 +76,7 @@ class SfpDebugWindow(tk.Toplevel):
self.image_area_size = 150
self.ip_var = tk.StringVar(value="127.0.0.1")
self.local_port_var = tk.StringVar(value="60002")
self.server_port_var = tk.StringVar(value="60001")
self.server_port_var = tk.StringVar(value="60003")
self.script_var = tk.StringVar(value="print('hello from client')")
self.tgt_id_var = tk.IntVar(value=DEF_TEST_ID)
self.tgt_range_var = tk.DoubleVar(value=DEF_TEST_RANGE)
@ -677,9 +677,10 @@ class SfpDebugWindow(tk.Toplevel):
command_str = command_builder.build_tgtset_from_target_state(
temp_target, include_flags=True
)
command_str = command_str.strip()
if not command_str.endswith("\n"):
command_str += "\n"
# Normalize/prefix legacy textual commands so the server receives the
# expected leading '$' and a trailing newline. Also log the final
# payload shown exactly as sent.
command_str = self._ensure_legacy_prefixed(command_str)
self._log_to_widget(f"Built command: {command_str!r}", "INFO")
success = self.shared_communicator._send_single_command(command_str)
@ -818,6 +819,8 @@ class SfpDebugWindow(tk.Toplevel):
return
try:
command_str = self.script_var.get()
# Ensure legacy/textual script commands are prefixed with '$' as expected by server
command_str = self._ensure_legacy_prefixed(command_str)
self.shared_communicator._send_single_command(command_str)
except (ValueError, tk.TclError) as e:
self._log_to_widget(
@ -833,6 +836,8 @@ class SfpDebugWindow(tk.Toplevel):
return False
try:
# Normalize legacy textual commands (prefix with $) before sending.
command_str = self._ensure_legacy_prefixed(command_str)
success = self.shared_communicator._send_single_command(command_str)
if success:
self._log_to_widget(f"Successfully sent command: {command_str}", "INFO")
@ -908,9 +913,7 @@ class SfpDebugWindow(tk.Toplevel):
return False
else:
command_str = command_builder.build_tgtset_selective(target_id, updates)
command_str = command_str.strip()
if command_str and not command_str.endswith("\n"):
command_str = command_str + "\n"
# _on_send_simple_command will normalize/prefix as needed
return self._on_send_simple_command(command_str)
except (ValueError, tk.TclError) as e:
self._log_to_widget(f"ERROR: Invalid input for tgtset: {e}", "ERROR")
@ -1329,6 +1332,33 @@ class SfpDebugWindow(tk.Toplevel):
self.log_tab.config(state=tk.DISABLED)
self.log_tab.see(tk.END)
def _ensure_legacy_prefixed(self, command: str) -> str:
"""Normalize textual/legacy commands: ensure they end with a newline.
If the string looks like JSON (starts with '{' or '['), do not alter it
other than ensuring a trailing newline. Bytes are decoded as UTF-8.
Former behavior prefixed '$' to legacy commands; that has been removed
because the DSP expects plain 'tgtset' commands.
"""
try:
if isinstance(command, (bytes, bytearray)):
s = command.decode("utf-8")
else:
s = str(command)
except Exception:
s = str(command)
s = s.strip()
if not s:
return s
# If it looks like JSON (starts with { or [), leave structure intact
# but ensure a trailing newline. For legacy textual commands, do not
# add any special prefix — just ensure newline.
if not s.endswith("\n"):
s = s + "\n"
return s
def _on_save_ris_csv(self):
try:
import csv

View File

@ -10,7 +10,7 @@ import os
from target_simulator.core.sfp_transport import SfpTransport
LISTEN_IP = "127.0.0.1"
LISTEN_PORT = 60001
LISTEN_PORT = 60003
CLIENT_BIND_PORT = 60002
received = []