SXXXXXXX_FlightMonitor/todo.md

174 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Certamente! È un'ottima idea avere un piano di sviluppo aggiornato e chiaro per tenere traccia dei progressi e dei passi successivi.
Ecco una versione rivista e dettagliata del piano di sviluppo, che include quanto fatto finora e i prossimi passi che abbiamo discusso. Ho cercato di mantenere la struttura a fasi, ma ho integrato le nuove comprensioni e priorità.
---
## **Piano di Sviluppo: FlightMonitor Application**
**🎯 Obiettivo Principale dell'Applicazione:**
Monitorare il traffico aereo in tempo reale (live) e analizzare voli passati (storico) tramite una GUI Tkinter, con visualizzazione testuale e grafica (mappa/lista).
**🧱 Architettura Proposta (Modulare):**
* **GUI (Tkinter):** `MainWindow`, Viste specifiche (Live, Storico), Widget riutilizzabili.
* **Controller:** Gestione eventi GUI, coordinamento moduli, logica applicativa principale.
* **Data Layer:**
* **Adapters:** Moduli specifici per provider (es. `OpenSkyLiveAdapter`) che recuperano dati grezzi e li trasformano in...
* **Common Models:** Modelli dati canonici (`CanonicalFlightState`) usati internamente dall'applicazione.
* **Storage:** Gestione della persistenza dei dati (es. `DataStorage` per file SQLite giornalieri).
* **Configuration:** Gestione delle impostazioni globali (`config.py`).
* **Utils:** Moduli di utilità (es. `logger.py`).
* **Business Logic (Futuro):** Filtri avanzati, analisi, allerte (potrebbero risiedere nel controller o in un modulo `logic/` separato).
---
**📋 Fasi di Sviluppo e Priorità:**
**✔️ Fase 0 Fondamenta e Setup Iniziale (Completata)**
* [X] Struttura base del progetto (cartelle `gui`, `controller`, `data`, `utils`).
* [X] Entry point `__main__.py`.
* [X] Modulo di configurazione base (`data/config.py`).
* [X] Modulo di logging robusto e configurabile (`utils/logger.py`) con output su console e GUI.
**✔️ Fase 1 GUI Minimale e Interazione Base (Completata)**
* [X] `MainWindow` (`gui/main_window.py`) con layout di base:
* [X] Controlli (selezione modalità Live/Storico, pulsanti Start/Stop).
* [X] Input per Bounding Box (lat/lon min/max).
* [X] Area di output iniziale (Canvas per la mappa).
* [X] Area per i log testuali (`ScrolledText`).
* [X] Status Bar con semaforo visivo e messaggi di testo.
* [X] `AppController` (`controller/app_controller.py`) per:
* [X] Gestire gli eventi base della GUI (cambio modalità, start/stop).
* [X] Coordinare l'interazione tra GUI e logica dati (inizialmente placeholder).
**✔️ Fase 2 Modalità Live: Fetching Asincrono e Visualizzazione Base (Completata)**
* [X] Definizione Modelli Dati Canonici (`data/common_models.py` -> `CanonicalFlightState`).
* [X] `OpenSkyLiveAdapter` (`data/opensky_live_adapter.py`):
* [X] Esecuzione in un thread separato (`threading.Thread`).
* [X] Polling periodico dell'API OpenSky (`/states/all`) per un bounding box.
* [X] Parsing della risposta JSON e trasformazione dei dati grezzi in oggetti `CanonicalFlightState`.
* [X] Gestione robusta degli errori API (incluso HTTP 429 Rate Limit) con strategia di **backoff esponenziale**.
* [X] Comunicazione asincrona con `AppController` tramite `queue.Queue`.
* [X] Invio di messaggi strutturati (dati di volo o messaggi di stato/errore) sulla coda.
* [X] `AppController` aggiornato per:
* [X] Gestire il ciclo di vita dell' `OpenSkyLiveAdapter` (avvio/arresto).
* [X] Consumare messaggi (dati e stati) dalla coda dell'adapter.
* [X] Interpretare i messaggi di stato dell'adapter e aggiornare la GUI.
* [X] `MainWindow` aggiornata per:
* [X] Visualizzare i voli (`List[CanonicalFlightState]`) sul `tk.Canvas` (punti e etichette base).
* [X] Utilizzare il metodo `update_semaphore_and_status` per riflettere lo stato comunicato dall'`AppController`.
**✔️ Fase 3 Persistenza Dati Live (Completata)**
* [X] `DataStorage` (`data/storage.py`):
* [X] Logica per creare e gestire file **SQLite giornalieri** (basati su data UTC).
* [X] Creazione automatica della directory dei database e delle tabelle (`flights`, `positions`) se non esistono.
* [X] Schema DB definito per memorizzare dati da `CanonicalFlightState` (inclusi timestamp, altitudini, velocità, ecc., e campi aggiuntivi come `squawk`, `spi`, `raw_data_provider`).
* [X] Metodi `add_or_update_flight_daily` e `add_position_daily` che accettano/usano `CanonicalFlightState`.
* [X] Integrazione in `AppController`:
* [X] Quando si ricevono `CanonicalFlightState` dall'adapter, vengono passati a `DataStorage` per il salvataggio nel DB giornaliero appropriato.
* [X] Gestione dell'inizializzazione e chiusura della connessione a `DataStorage`.
---
**📍 Punto Attuale (Dopo Fase 3):**
* L'applicazione può recuperare dati live da OpenSky per un'area definita.
* I dati vengono aggiornati periodicamente senza bloccare la GUI.
* Gli errori API (come rate limit) sono gestiti con backoff.
* Lo stato dell'applicazione e del fetching è comunicato all'utente tramite una status bar con semaforo e messaggi.
* I dati live recuperati vengono salvati in file SQLite giornalieri.
* La struttura del codice è modulare e utilizza modelli dati canonici, preparandoci per future estensioni.
---
**➡️ Fase 4 Modalità Storico: Visualizzazione e Filtri Base (Prossima Priorità Alta)**
* **Caricamento Dati Storici:**
* Implementare la logica in `DataStorage` per interrogare i file SQLite giornalieri.
* Metodo per ottenere voli e/o posizioni per un dato intervallo di tempo (che potrebbe coinvolgere l'apertura di più file giornalieri).
* Metodo per cercare voli per `icao24` o `callsign` in un range di date.
* **GUI per la Modalità Storico (`gui/history_view.py` o integrazione in `MainWindow`):**
* Input per selezionare l'intervallo di date/ore.
* Input per filtri base (es. ICAO24, callsign, forse aeroporto se avessimo quei dati).
* Pulsante per caricare/visualizzare i dati storici.
* **Visualizzazione Dati Storici:**
* Tabella (`ttk.Treeview` o un widget `FlightTable` personalizzato) per mostrare la lista dei voli e/o le loro posizioni.
* Opzionale: Visualizzazione statica della traccia di un volo selezionato sul `tk.Canvas`.
* **`AppController`:**
* Logica per `start_history_monitoring` e `stop_history_monitoring`.
* Interazione con `DataStorage` per recuperare i dati.
* Passaggio dei dati storici alla GUI per la visualizzazione.
**➡️ Fase 5 Funzionalità Avanzate e Miglioramenti**
* **Miglioramenti Mappa (Media Priorità):**
* Valutare l'integrazione di una libreria di mappe più avanzata (es. `tkintermapview` o `folium` se si considera un output web/HTML separato, anche se `tkintermapview` è più integrato).
* Disegnare icone di aerei più realistiche (magari orientate in base al `true_track`).
* Possibilità di cliccare su un aereo per vedere più dettagli.
* Visualizzazione delle tracce dei voli (dallo storico o segmenti live).
* **Analisi Semplice (Business Logic - Media Priorità):**
* Creare un modulo `logic/analytics.py`.
* Funzioni per calcolare statistiche base dai dati storici (es. numero di voli per ora/giorno, rotte più frequenti in un'area, altitudini medie).
* Visualizzazione di queste analisi nella GUI.
* **Filtri Avanzati (Media Priorità):**
* Creare `logic/filters.py`.
* Filtri dinamici applicabili sia ai dati live che storici (tipo di aereo, compagnia richiederebbe dati aggiuntivi altitudine, velocità).
* **Recupero Dati Storici da API Esterne (Bassa/Media Priorità, come discusso):**
* Implementare la logica (magari in un `OpenSkyHistoryAdapter`) per scaricare dati storici da OpenSky (o altri provider) se mancano nei nostri DB giornalieri.
* Questo si integrerebbe con la Fase 4, quando si cercano dati storici.
* **Configurazioni Utente (Bassa/Media Priorità):**
* Salvataggio/caricamento delle preferenze utente (es. ultimo bounding box usato, tema GUI, API keys se necessarie).
* Finestra di dialogo per le impostazioni.
* **Esportazione Dati (Bassa Priorità):**
* Funzionalità per esportare i dati selezionati (live o storici) in formati come CSV o JSON.
**➡️ Fase 6 Pulizia, Test, Documentazione e Rilascio (Continua)**
* **Test Unitari:** Scrivere unit test per i componenti core (modelli, adapter, storage, logica di business).
* **Test di Integrazione:** Testare il flusso completo dell'applicazione.
* **Refactoring e Pulizia Codice:** Continuare a migliorare la qualità del codice.
* **Documentazione:**
* Migliorare docstring e commenti.
* Scrivere/aggiornare `README.md` con istruzioni d'uso, setup, dipendenze.
* **Gestione Dipendenze:** (es. `requirements.txt`).
* **Packaging (Opzionale):** Creare un eseguibile distribuibile (es. con PyInstaller).
---
Questo piano è una guida; le priorità possono cambiare e nuove idee possono emergere. Spero che questa visione d'insieme ti sia utile! Abbiamo fatto ottimi progressi sulle fondamenta e sulla modalità live. La Fase 4 sulla modalità storico sarà il prossimo grande blocco di funzionalità.
Certamente. Ho analizzato il codice che mi hai fornito per i moduli `__main__.py`, `common_models.py`, `storage.py`, `logging_config.py`, `__init__.py`, `opensky_live_adapter.py`, `config.py`, `main_window.py`, `app_controller.py`, `map_canvas_manager.py`, `map_services.py`, `map_drawing.py`, `map_utils.py`, `map_tile_manager.py`, e `map_manager.py`.
Ho verificato le importazioni, le chiamate tra funzioni e classi nei diversi moduli e la coerenza generale dell'architettura definita dal codice.
L'architettura generale che prevede un `AppController` che gestisce la logica applicativa, un `MainWindow` per la GUI, moduli per la gestione dei dati (`storage`, `common_models`), moduli per la comunicazione con sorgenti esterne (`opensky_live_adapter`), e moduli per la visualizzazione mappa (`map_canvas_manager`, `map_tile_manager`, `map_services`, `map_utils`, `map_drawing`) sembra ben definita e le interazioni tra questi componenti sono in gran parte corrette, con il controller che fa da mediatore tra la GUI e i worker threads/moduli dati, comunicando spesso tramite code per garantire la thread-safety con la GUI Tkinter.
L'uso dei `try/except ImportError` per le librerie opzionali (`pyproj`, `mercantile`, `Pillow`, `cv2`/`numpy`) e dei controlli `winfo_exists()` prima di interagire con i widget Tkinter è una buona pratica che aumenta la robustezza dell'applicazione.
Tuttavia, ho riscontrato alcune incongruenze o aree che potrebbero essere migliorate per garantire una separazione più pulita delle responsabilità e correggere piccole imprecisioni.
Ecco i punti specifici che ho identificato:
1. **Interazione Diretta GUI nell'Adapter `OpenSkyLiveAdapter`**:
* **Dove:** Modulo `opensky_live_adapter.py`, in particolare nei metodi `_send_status_to_queue` e `run`.
* **Incongruenza:** L'adapter (`OpenSkyLiveAdapter`) è un thread worker che dovrebbe essere completamente disaccoppiato dalla GUI. La sua unica forma di comunicazione verso l'esterno dovrebbe essere la `output_queue`. Invece, il codice contiene riferimenti diretti all'istanza di `main_window` (`self.main_window`) e controlli come `self.main_window.root.winfo_exists()` prima di inviare messaggi di stato alla coda.
* **Perché è un problema:** L'accesso diretto a un widget Tkinter (`self.main_window.root`) o il controllo del suo stato (`winfo_exists()`) da un thread diverso da quello principale di Tkinter **non è thread-safe** e può portare a `TclError` imprevedibili, specialmente durante la chiusura dell'applicazione o in caso di errori nella GUI. L'adapter non dovrebbe mai "sapere" dell'esistenza della finestra principale.
* **Come dovrebbe essere gestito:** L'adapter dovrebbe semplicemente mettere *sempre* i messaggi di stato nella `output_queue`. È compito del `AppController` (che processa la coda sul thread principale Tkinter usando `root.after`) leggere questi messaggi e, solo a quel punto, decidere se e come aggiornare la GUI (`main_window`). I controlli `if self.main_window and hasattr(...) and self.main_window.root.winfo_exists()` devono essere spostati dall'adapter al `_process_flight_data_queue` nel `AppController` (dove in parte già ci sono, ma non per *tutte* le azioni che l'adapter tenta di fare direttamente).
2. **Dipendenza da Moduli Esterni (`geoelevation`) nel Disegno Mappa**:
* **Dove:** Moduli `map_drawing.py` e `map_tile_manager.py`.
* **Incongruenza:** Il codice importa costanti e potenzialmente classi/funzioni dai percorsi `geoelevation.image_processor` e `.geo_map_viewer`. Questi moduli (`geoelevation`) non sono inclusi nel codice fornito e sembrano appartenere a un progetto o libreria separata.
* **Perché è un potenziale problema:** Se questi moduli esterni non sono disponibili nell'ambiente di esecuzione, le importazioni falliranno. Sebbene l'uso dei `try/except ImportError` e la definizione di valori di fallback per le costanti (`DEM_BOUNDARY_COLOR`, `DEFAULT_FONT`, ecc.) mitighino il rischio di crash, alcune funzionalità di disegno o lo stile visivo previsto potrebbero non essere disponibili.
* **Stato Attuale:** Il codice attuale gestisce la cosa in modo robusto con fallback e logging di warning/error, quindi non causa un blocco critico dell'applicazione, ma è una dipendenza non fornita che limita la piena funzionalità del disegno mappa.
3. **Controllo Redondante/Errato nel `MapTileManager`**:
* **Dove:** Modulo `map_tile_manager.py`, metodo `_get_bounds_for_tile_range`.
* **Incongruenza:** Il codice controlla la disponibilità della libreria `mercantile` utilizzando il flag `MERCANTILE_MODULE_LOCALLY_AVAILABLE`, che però è definito nel modulo `map_utils.py` e non è importato né definito in `map_tile_manager.py`. Di conseguenza, questo flag non esisterà nel namespace di `map_tile_manager.py` e causerà un `NameError` se `mercantile` non è disponibile all'importazione in quel modulo. Il controllo corretto nel contesto di `map_tile_manager.py` è verificare se la variabile locale `mercantile` (importata all'inizio del file con `try/except`) è `None`.
* **Stato Attuale:** Fortunatamente, il codice include già anche il controllo corretto `if mercantile is None:`, che è quello che effettivamente funziona se `mercantile` non viene importato. Il controllo errato con il flag `MERCANTILE_MODULE_LOCALLY_AVAILABLE` è semplicemente redondante e, di per sé, errato.
4. **Coerenza Nomi Variabili/Chiavi:**
* **Dove:** Modulo `map_utils.py`, metodo `get_combined_geographic_bounds_from_tile_info_list`.
* **Incongruenza:** Nella versione che ho analizzato, c'era un probabile errore di battitura `longitude_longitude` al posto di `longitude_coord` quando si accedeva al dizionario `tile_info`.
* **Stato Attuale:** Nello snippet fornito, questa correzione (`longitude_coord`) sembra già essere stata applicata, rendendo questo punto non più un'incongruenza nel codice attuale, ma è bene notarlo come potenziale area di attenzione in versioni precedenti o future se si ripresentasse l'errore.
A parte il punto 1 (l'interazione diretta GUI dall'adapter, che è un rischio per la stabilità dell'applicazione), gli altri punti sono gestiti in modo che l'applicazione possa comunque funzionare, sebbene con funzionalità potenzialmente ridotte in assenza di librerie o moduli esterni.
Il resto del codice, inclusa la gestione della coda nel controller, l'inizializzazione del logging thread-safe, l'uso dei modelli canonici e la logica di base dello storage, appare consistente e ben strutturato all'interno dei file forniti.
Sono pronto a procedere non appena mi dirai quali modifiche desideri apportare, tenendo conto di questa analisi.