configurazione salvataggi esterni al modulo
This commit is contained in:
parent
28f5fda397
commit
bef6cf6f08
@ -49,6 +49,8 @@ class DumpManager:
|
||||
self._video_fps_map: Dict[str, float] = {}
|
||||
# Maximum duplicate frames to write when spacing is large (safety cap)
|
||||
self._max_duplicate_frames = 1000
|
||||
# Track last produced video file paths per category
|
||||
self._video_paths: Dict[str, str] = {}
|
||||
|
||||
# prune existing files at startup
|
||||
for cat in list(self._saved.keys()):
|
||||
@ -112,6 +114,8 @@ class DumpManager:
|
||||
return False
|
||||
self._video_writers[category] = writer
|
||||
self._video_start_times[category] = time.time()
|
||||
# remember video path for later retrieval
|
||||
self._video_paths[category] = path
|
||||
# store configured fps per category
|
||||
try:
|
||||
self._video_fps_map[category] = float(fps)
|
||||
@ -171,6 +175,10 @@ class DumpManager:
|
||||
self._video_writers.pop(category, None)
|
||||
self._video_start_times.pop(category, None)
|
||||
self._last_frame_timestamps.pop(category, None)
|
||||
try:
|
||||
self._video_paths.pop(category, None)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _enqueue(self, path: str, category: str) -> None:
|
||||
"""Track saved file and trigger pruning."""
|
||||
@ -178,6 +186,38 @@ class DumpManager:
|
||||
self._saved[cat].append(path)
|
||||
self._prune_category(cat)
|
||||
|
||||
def get_last_saved(self, category: str) -> Optional[str]:
|
||||
"""Return the last saved preview path for a category, or None."""
|
||||
try:
|
||||
cat = category if category in self._saved else 'unknown'
|
||||
if not self._saved.get(cat):
|
||||
return None
|
||||
return self._saved[cat][-1]
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def get_last_video_path(self, category: Optional[str] = None) -> Optional[str]:
|
||||
"""Return the last started video path.
|
||||
|
||||
If `category` is provided, return that category's last video path.
|
||||
Otherwise return the most-recently-started video across categories.
|
||||
"""
|
||||
try:
|
||||
if category:
|
||||
return self._video_paths.get(category)
|
||||
# choose latest by _video_start_times
|
||||
best_cat = None
|
||||
best_ts = 0.0
|
||||
for cat, ts in self._video_start_times.items():
|
||||
if ts and ts > best_ts:
|
||||
best_ts = ts
|
||||
best_cat = cat
|
||||
if best_cat:
|
||||
return self._video_paths.get(best_cat)
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _prune_category(self, category: str) -> None:
|
||||
"""Remove oldest files if they exceed the keep limit."""
|
||||
prefix = f'VideoReceiverSFP_{category}_'
|
||||
|
||||
@ -1262,6 +1262,36 @@ class SfpConnectorModule:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# --- API: last saved file paths -------------------------------------
|
||||
def get_last_saved_mfd(self) -> Optional[str]:
|
||||
try:
|
||||
if getattr(self, '_dump_manager', None) is not None:
|
||||
return self._dump_manager.get_last_saved('mfd')
|
||||
# fallback: check module-level saved lists
|
||||
if getattr(self, '_saved_pngs', None):
|
||||
return self._saved_pngs[-1] if len(self._saved_pngs) else None
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_last_saved_sar(self) -> Optional[str]:
|
||||
try:
|
||||
if getattr(self, '_dump_manager', None) is not None:
|
||||
return self._dump_manager.get_last_saved('sar')
|
||||
if getattr(self, '_saved_sar_pngs', None):
|
||||
return self._saved_sar_pngs[-1] if len(self._saved_sar_pngs) else None
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_last_video_path(self, category: Optional[str] = None) -> Optional[str]:
|
||||
try:
|
||||
if getattr(self, '_dump_manager', None) is not None:
|
||||
return self._dump_manager.get_last_video_path(category)
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def update_mfd_lut(self, lut) -> None:
|
||||
"""Receive an MFD LUT (numpy array or similar) from the UI and store it.
|
||||
|
||||
|
||||
@ -128,7 +128,119 @@ def run_orchestrator():
|
||||
main_frame.columnconfigure(1, weight=1)
|
||||
main_frame.rowconfigure(1, weight=1) # The viewer row is the one that grows
|
||||
|
||||
# --- Row 0b: Last saved paths (for copy/paste) ---
|
||||
paths_frame = ttk.Frame(controls_box)
|
||||
paths_frame.pack(fill='x', expand=False, pady=(6,0))
|
||||
|
||||
mfd_img_save_var = tk.BooleanVar(value=bool(getattr(module, '_save_png', False)))
|
||||
mfd_img_cb = ttk.Checkbutton(paths_frame, text='Last MFD file image', variable=mfd_img_save_var)
|
||||
mfd_img_cb.grid(row=0, column=0, sticky='w', padx=5)
|
||||
last_mfd_var = tk.StringVar(value="")
|
||||
last_mfd_entry = ttk.Entry(paths_frame, textvariable=last_mfd_var, width=80, state='readonly')
|
||||
last_mfd_entry.grid(row=0, column=1, padx=5, sticky='w')
|
||||
def _copy_mfd():
|
||||
try:
|
||||
root.clipboard_clear()
|
||||
root.clipboard_append(last_mfd_var.get() or '')
|
||||
except Exception:
|
||||
pass
|
||||
ttk.Button(paths_frame, text='Copy', command=_copy_mfd, width=6).grid(row=0, column=2, padx=4)
|
||||
|
||||
sar_img_save_var = tk.BooleanVar(value=bool(getattr(module, '_sar_save_png', False)))
|
||||
sar_img_cb = ttk.Checkbutton(paths_frame, text='Last SAR file image', variable=sar_img_save_var)
|
||||
sar_img_cb.grid(row=1, column=0, sticky='w', padx=5)
|
||||
last_sar_var = tk.StringVar(value="")
|
||||
last_sar_entry = ttk.Entry(paths_frame, textvariable=last_sar_var, width=80, state='readonly')
|
||||
last_sar_entry.grid(row=1, column=1, padx=5, sticky='w')
|
||||
def _copy_sar():
|
||||
try:
|
||||
root.clipboard_clear()
|
||||
root.clipboard_append(last_sar_var.get() or '')
|
||||
except Exception:
|
||||
pass
|
||||
ttk.Button(paths_frame, text='Copy', command=_copy_sar, width=6).grid(row=1, column=2, padx=4)
|
||||
|
||||
mfd_vid_save_var = tk.BooleanVar(value=bool(getattr(module, '_record_mfd_video', False)))
|
||||
mfd_vid_cb = ttk.Checkbutton(paths_frame, text='Last MFD file video', variable=mfd_vid_save_var)
|
||||
mfd_vid_cb.grid(row=2, column=0, sticky='w', padx=5)
|
||||
last_mfd_vid_var = tk.StringVar(value="")
|
||||
last_mfd_vid_entry = ttk.Entry(paths_frame, textvariable=last_mfd_vid_var, width=80, state='readonly')
|
||||
last_mfd_vid_entry.grid(row=2, column=1, padx=5, sticky='w')
|
||||
def _copy_mfd_vid():
|
||||
try:
|
||||
root.clipboard_clear()
|
||||
root.clipboard_append(last_mfd_vid_var.get() or '')
|
||||
except Exception:
|
||||
pass
|
||||
ttk.Button(paths_frame, text='Copy', command=_copy_mfd_vid, width=6).grid(row=2, column=2, padx=4)
|
||||
|
||||
sar_vid_save_var = tk.BooleanVar(value=bool(getattr(module, '_record_sar_video', False)))
|
||||
sar_vid_cb = ttk.Checkbutton(paths_frame, text='Last SAR file video', variable=sar_vid_save_var)
|
||||
sar_vid_cb.grid(row=3, column=0, sticky='w', padx=5)
|
||||
last_sar_vid_var = tk.StringVar(value="")
|
||||
last_sar_vid_entry = ttk.Entry(paths_frame, textvariable=last_sar_vid_var, width=80, state='readonly')
|
||||
last_sar_vid_entry.grid(row=3, column=1, padx=5, sticky='w')
|
||||
def _copy_sar_vid():
|
||||
try:
|
||||
root.clipboard_clear()
|
||||
root.clipboard_append(last_sar_vid_var.get() or '')
|
||||
except Exception:
|
||||
pass
|
||||
ttk.Button(paths_frame, text='Copy', command=_copy_sar_vid, width=6).grid(row=3, column=2, padx=4)
|
||||
|
||||
def _refresh_paths():
|
||||
try:
|
||||
m = module.get_last_saved_mfd()
|
||||
s = module.get_last_saved_sar()
|
||||
vm = module.get_last_video_path('mfd')
|
||||
vs = module.get_last_video_path('sar')
|
||||
try:
|
||||
last_mfd_var.set(m or '')
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
last_sar_var.set(s or '')
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
last_mfd_vid_var.set(vm or '')
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
last_sar_vid_var.set(vs or '')
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
ttk.Button(paths_frame, text='Refresh Paths', command=_refresh_paths).grid(row=0, column=3, rowspan=4, padx=8)
|
||||
|
||||
# initial refresh
|
||||
try:
|
||||
_refresh_paths()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Periodic automatic refresh of last-saved paths (every 2 seconds)
|
||||
def _periodic_refresh():
|
||||
try:
|
||||
_refresh_paths()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
root.after(2000, _periodic_refresh)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
root.after(2000, _periodic_refresh)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Callbacks for Parameters
|
||||
# Track whether the user has started a 'manual' recording session
|
||||
user_recording_active_var = tk.BooleanVar(value=False)
|
||||
|
||||
def on_mfd_param_changed(param_type, name, value):
|
||||
try:
|
||||
if param_type == 'save_png':
|
||||
@ -208,20 +320,108 @@ def run_orchestrator():
|
||||
|
||||
# Button Actions
|
||||
def on_start_recording():
|
||||
# Read desired targets from checkboxes and only apply when starting
|
||||
save_mfd = bool(mfd_img_save_var.get())
|
||||
save_sar = bool(sar_img_save_var.get())
|
||||
rec_mfd = bool(mfd_vid_save_var.get())
|
||||
rec_sar = bool(sar_vid_save_var.get())
|
||||
|
||||
# If nothing selected, do nothing (per user request)
|
||||
if not (save_mfd or save_sar or rec_mfd or rec_sar):
|
||||
return
|
||||
|
||||
# Apply selections to module: image saving and video recording only while 'recording'
|
||||
try:
|
||||
module.set_save_png(save_mfd)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
module.set_sar_save_png(save_sar)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
module.set_record_mfd_video(rec_mfd)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
module.set_record_sar_video(rec_sar)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Mark that user requested recording (even if only image saving)
|
||||
try:
|
||||
user_recording_active_var.set(True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Lock checkboxes while recording/armed
|
||||
try:
|
||||
mfd_img_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_img_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
mfd_vid_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_vid_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
start_rec_btn.config(state=tk.DISABLED)
|
||||
stop_rec_btn.config(state=tk.NORMAL)
|
||||
rec_status_var.set("Recording...")
|
||||
rec_status_label.config(foreground="red")
|
||||
module.set_record_mfd_video(True)
|
||||
module.set_record_sar_video(True)
|
||||
|
||||
|
||||
def on_stop_recording():
|
||||
# Stop all recording/saving targets and unlock checkboxes
|
||||
try:
|
||||
module.set_record_mfd_video(False)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
module.set_record_sar_video(False)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
module.set_save_png(False)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
module.set_sar_save_png(False)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
mfd_img_cb.config(state=tk.NORMAL)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_img_cb.config(state=tk.NORMAL)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
mfd_vid_cb.config(state=tk.NORMAL)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_vid_cb.config(state=tk.NORMAL)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
user_recording_active_var.set(False)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
start_rec_btn.config(state=tk.NORMAL)
|
||||
stop_rec_btn.config(state=tk.DISABLED)
|
||||
rec_status_var.set("Not Recording")
|
||||
rec_status_label.config(foreground="gray")
|
||||
module.set_record_mfd_video(False)
|
||||
module.set_record_sar_video(False)
|
||||
|
||||
start_rec_btn.config(command=on_start_recording)
|
||||
stop_rec_btn.config(command=on_stop_recording)
|
||||
@ -229,7 +429,9 @@ def run_orchestrator():
|
||||
# Periodically update recording status indicator based on module state
|
||||
def _update_record_status():
|
||||
try:
|
||||
armed = bool(getattr(module, '_record_mfd_video', False) or getattr(module, '_record_sar_video', False))
|
||||
# consider user-initiated recording as 'armed' even if video flags are not set
|
||||
manual = bool(user_recording_active_var.get())
|
||||
armed = manual or bool(getattr(module, '_record_mfd_video', False) or getattr(module, '_record_sar_video', False))
|
||||
active_mfd = bool(getattr(module, '_mfd_video_active', False))
|
||||
active_sar = bool(getattr(module, '_sar_video_active', False))
|
||||
if active_mfd or active_sar:
|
||||
@ -242,16 +444,64 @@ def run_orchestrator():
|
||||
rec_status_label.config(foreground="red")
|
||||
start_rec_btn.config(state=tk.DISABLED)
|
||||
stop_rec_btn.config(state=tk.NORMAL)
|
||||
try:
|
||||
mfd_vid_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_vid_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
mfd_img_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_img_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
elif armed:
|
||||
rec_status_var.set("Armed (waiting for first frame)")
|
||||
rec_status_label.config(foreground="orange")
|
||||
start_rec_btn.config(state=tk.DISABLED)
|
||||
stop_rec_btn.config(state=tk.NORMAL)
|
||||
try:
|
||||
mfd_vid_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_vid_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
mfd_img_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_img_cb.config(state=tk.DISABLED)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
rec_status_var.set("Not Recording")
|
||||
rec_status_label.config(foreground="gray")
|
||||
start_rec_btn.config(state=tk.NORMAL)
|
||||
stop_rec_btn.config(state=tk.DISABLED)
|
||||
try:
|
||||
mfd_vid_cb.config(state=tk.NORMAL)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_vid_cb.config(state=tk.NORMAL)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
mfd_img_cb.config(state=tk.NORMAL)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
sar_img_cb.config(state=tk.NORMAL)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
|
||||
2
todos.md
2
todos.md
@ -7,7 +7,7 @@
|
||||
- [ ] VRSFP: aggiungere la possibilità di modificare la configurazione rutime, com e poter aggiungere la possibilità di salvare le immagini invece che il video o altro: creare una funzione setConfig che permetta di modificare runtime la configurazione del modulo. La stessa informazioni come formato deve essere la stessa che viene passata in fase di inizializzazione. Visto che la configurazione possa essere modificata anche in altre parti sarebbe utile anche a vere una funzione che restituisca il dizionario della configurazione come get_config().
|
||||
- [x] VRSFP: poter aggiungere le funzioni di start salvataggio video e stop salvataggio video come api
|
||||
- [ ] VRSFP: poter impostare runtime il nome e la posizione del file immagine o video prodotto
|
||||
- [ ] VRSFP: avere una funzione che restituisce nome e path dell'ultimo file salvato per mfd, sar e video
|
||||
- [x] VRSFP: avere una funzione che restituisce nome e path dell'ultimo file salvato per mfd, sar e video
|
||||
- [x] VRSFP: aggiungere un log stile modulo aggiuntivo e collegarlo al modulo che poi sarà comune a tutti i moduli
|
||||
- [x] VRSFP: aggiungere un pannello al test_orchestator dove poter aggiungere i controlli per testare le funzionalità di registrazione ondemand ecc
|
||||
- [x] VRSFP: poter impostare a priori la dimensione in pixel della finestra mfd e della finestra sar. Per la finestra mfd, se viene indicato "0, 0 " viene usata la dimensione dell'immagine che viene spedita. se è diversa da 0,0 viene ridmensionata la finestra. Invece per il sar la dimensione è sempre quella specificata e deve sempre essere diversa da 0,0.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user