Merge pull request #8 from walidb212/fix/gui-settings-validation
fix(gui): validate radar settings before usb send
This commit is contained in:
@@ -47,10 +47,23 @@ DARK_ACCENT = "#3c3f41"
|
||||
DARK_HIGHLIGHT = "#4e5254"
|
||||
DARK_BORDER = "#555555"
|
||||
DARK_TEXT = "#cccccc"
|
||||
DARK_BUTTON = "#3c3f41"
|
||||
DARK_BUTTON_HOVER = "#4e5254"
|
||||
DARK_TREEVIEW = "#3c3f41"
|
||||
DARK_TREEVIEW_ALT = "#404040"
|
||||
DARK_BUTTON = "#3c3f41"
|
||||
DARK_BUTTON_HOVER = "#4e5254"
|
||||
DARK_TREEVIEW = "#3c3f41"
|
||||
DARK_TREEVIEW_ALT = "#404040"
|
||||
|
||||
RADAR_SETTINGS_LIMITS = {
|
||||
'system_frequency': (1e9, 100e9),
|
||||
'chirp_duration_1': (1e-6, 1000e-6),
|
||||
'chirp_duration_2': (0.1e-6, 10e-6),
|
||||
'chirps_per_position': (1, 256),
|
||||
'freq_min': (1e6, 100e6),
|
||||
'freq_max': (1e6, 100e6),
|
||||
'prf1': (100, 10000),
|
||||
'prf2': (100, 10000),
|
||||
'max_distance': (100, 100000),
|
||||
'map_size': (1000, 200000),
|
||||
}
|
||||
|
||||
@dataclass
|
||||
class RadarTarget:
|
||||
@@ -1125,10 +1138,10 @@ class RadarGUI:
|
||||
self.map_info_label = ttk.Label(info_frame, text="No GPS data received yet", font=('Arial', 10))
|
||||
self.map_info_label.pack()
|
||||
|
||||
def setup_settings_tab(self):
|
||||
"""Setup the settings tab with additional chirp durations and map size"""
|
||||
settings_frame = ttk.Frame(self.tab_settings)
|
||||
settings_frame.pack(fill='both', expand=True, padx=10, pady=10)
|
||||
def setup_settings_tab(self):
|
||||
"""Setup the settings tab with additional chirp durations and map size"""
|
||||
settings_frame = ttk.Frame(self.tab_settings)
|
||||
settings_frame.pack(fill='both', expand=True, padx=10, pady=10)
|
||||
|
||||
entries = [
|
||||
('System Frequency (Hz):', 'system_frequency', 10e9),
|
||||
@@ -1153,8 +1166,40 @@ class RadarGUI:
|
||||
entry.grid(row=i, column=1, padx=5, pady=5)
|
||||
self.settings_vars[attr] = var
|
||||
|
||||
ttk.Button(settings_frame, text="Apply Settings",
|
||||
command=self.apply_settings).grid(row=len(entries), column=0, columnspan=2, pady=10)
|
||||
ttk.Button(settings_frame, text="Apply Settings",
|
||||
command=self.apply_settings).grid(row=len(entries), column=0, columnspan=2, pady=10)
|
||||
|
||||
def _parse_settings_from_form(self):
|
||||
"""Read settings from the UI and return a validated RadarSettings instance."""
|
||||
parsed_settings = RadarSettings(
|
||||
system_frequency=float(self.settings_vars['system_frequency'].get()),
|
||||
chirp_duration_1=float(self.settings_vars['chirp_duration_1'].get()),
|
||||
chirp_duration_2=float(self.settings_vars['chirp_duration_2'].get()),
|
||||
chirps_per_position=int(self.settings_vars['chirps_per_position'].get()),
|
||||
freq_min=float(self.settings_vars['freq_min'].get()),
|
||||
freq_max=float(self.settings_vars['freq_max'].get()),
|
||||
prf1=float(self.settings_vars['prf1'].get()),
|
||||
prf2=float(self.settings_vars['prf2'].get()),
|
||||
max_distance=float(self.settings_vars['max_distance'].get()),
|
||||
map_size=float(self.settings_vars['map_size'].get()),
|
||||
)
|
||||
|
||||
self._validate_radar_settings(parsed_settings)
|
||||
return parsed_settings
|
||||
|
||||
def _validate_radar_settings(self, settings):
|
||||
"""Mirror the firmware-side range checks before sending settings to STM32."""
|
||||
for field_name, (minimum, maximum) in RADAR_SETTINGS_LIMITS.items():
|
||||
value = getattr(settings, field_name)
|
||||
if value < minimum or value > maximum:
|
||||
raise ValueError(
|
||||
f"{field_name} must be between {minimum:g} and {maximum:g}."
|
||||
)
|
||||
|
||||
if settings.freq_max <= settings.freq_min:
|
||||
raise ValueError("freq_max must be greater than freq_min.")
|
||||
|
||||
return True
|
||||
|
||||
def apply_pitch_correction(self, raw_elevation, pitch_angle):
|
||||
"""
|
||||
@@ -1262,29 +1307,28 @@ class RadarGUI:
|
||||
|
||||
logging.info("Radar system stopped")
|
||||
|
||||
def apply_settings(self):
|
||||
"""Step 13: Apply and send radar settings via USB"""
|
||||
try:
|
||||
self.settings.system_frequency = float(self.settings_vars['system_frequency'].get())
|
||||
self.settings.chirp_duration_1 = float(self.settings_vars['chirp_duration_1'].get())
|
||||
self.settings.chirp_duration_2 = float(self.settings_vars['chirp_duration_2'].get())
|
||||
self.settings.chirps_per_position = int(self.settings_vars['chirps_per_position'].get())
|
||||
self.settings.freq_min = float(self.settings_vars['freq_min'].get())
|
||||
self.settings.freq_max = float(self.settings_vars['freq_max'].get())
|
||||
self.settings.prf1 = float(self.settings_vars['prf1'].get())
|
||||
self.settings.prf2 = float(self.settings_vars['prf2'].get())
|
||||
self.settings.max_distance = float(self.settings_vars['max_distance'].get())
|
||||
self.settings.map_size = float(self.settings_vars['map_size'].get())
|
||||
self.google_maps_api_key = self.settings_vars['google_maps_api_key'].get()
|
||||
|
||||
if self.stm32_usb_interface.is_open:
|
||||
self.stm32_usb_interface.send_settings(self.settings)
|
||||
|
||||
messagebox.showinfo("Success", "Settings applied and sent to STM32 via USB")
|
||||
logging.info("Radar settings applied via USB")
|
||||
|
||||
except ValueError as e:
|
||||
messagebox.showerror("Error", f"Invalid setting value: {e}")
|
||||
def apply_settings(self):
|
||||
"""Step 13: Apply and send radar settings via USB"""
|
||||
try:
|
||||
parsed_settings = self._parse_settings_from_form()
|
||||
self.google_maps_api_key = self.settings_vars['google_maps_api_key'].get()
|
||||
|
||||
self.settings = parsed_settings
|
||||
|
||||
if self.stm32_usb_interface.is_open:
|
||||
if not self.stm32_usb_interface.send_settings(self.settings):
|
||||
messagebox.showerror("Error", "Failed to send settings to STM32 via USB")
|
||||
logging.error("Radar settings validation passed, but USB send failed")
|
||||
return
|
||||
|
||||
messagebox.showinfo("Success", "Settings applied and sent to STM32 via USB")
|
||||
logging.info("Radar settings applied and sent via USB")
|
||||
else:
|
||||
messagebox.showinfo("Success", "Settings applied locally")
|
||||
logging.info("Radar settings applied locally; STM32 USB is not connected")
|
||||
|
||||
except ValueError as e:
|
||||
messagebox.showerror("Error", f"Invalid setting value: {e}")
|
||||
|
||||
def start_background_threads(self):
|
||||
"""Start background data processing threads"""
|
||||
|
||||
Reference in New Issue
Block a user