672 lines
21 KiB
Markdown
672 lines
21 KiB
Markdown
# Piano di Migrazione: GrifoScope → PyBusMonitor1553
|
||
|
||
## 📊 Situazione Attuale
|
||
|
||
### Sistema a 3 Componenti
|
||
|
||
```
|
||
┌─────────────────┐ UDP 1553 ┌─────────────────┐
|
||
│ GrifoScope │◄────────────────────────►│ Radar Server │
|
||
│ (BusMonitor) │ Port 50553 ← 60553 │ (Target Real) │
|
||
│ C++/Qt │ │ │
|
||
└─────────────────┘ └─────────────────┘
|
||
▲
|
||
│ DA SOSTITUIRE CON
|
||
▼
|
||
┌─────────────────┐ UDP 1553 ┌─────────────────┐
|
||
│PyBusMonitor1553 │◄────────────────────────►│ Radar Server │
|
||
│ (BusMonitor) │ Port 51553 ← 61553 │ (Target Real) │
|
||
│ Python │ │ │
|
||
└─────────────────┘ └─────────────────┘
|
||
```
|
||
|
||
**Obiettivo**: Far funzionare PyBusMonitor1553 esattamente come GrifoScope per comunicare con il Radar Server.
|
||
|
||
---
|
||
|
||
## 🔍 Analisi del Comportamento di GrifoScope
|
||
|
||
### 1. **Architettura di Comunicazione** (`qg1553overudp.cpp`)
|
||
|
||
GrifoScope usa un pattern **Bus Controller (BC)** che:
|
||
|
||
#### **Inizializzazione** (`Qg1553OverUdp::Implementation::BusGenerator()`)
|
||
```cpp
|
||
// Bind sulla porta locale 60553 (60000 + 1553)
|
||
s.bind(networkInterface(), 60000+1553);
|
||
|
||
// Indirizzo destinazione: broadcast o IP specifico radar
|
||
rtAddress = networkBroadcast(); // Es: 127.0.0.255
|
||
|
||
// Registra messaggi A (BC→RT, tr=0):
|
||
addMsg<msg_rdr_settings_and_parameters_t>(1, 0); // A1
|
||
addMsg<msg_rdr_operation_command_t>(2, 0); // A2
|
||
addMsg<msg_graphic_setting_t>(3, 0); // A3
|
||
addMsg<msg_nav_data_and_cursor_t>(4, 0); // A4
|
||
addMsg<msg_inu_high_speed_t>(5, 0); // A5
|
||
|
||
// Registra messaggi B (RT→BC, tr=1):
|
||
addMsg<msg_settings_tellback_t>(15, 1); // B6
|
||
addMsg<msg_rdr_status_tellback_t>(16, 1); // B7
|
||
```
|
||
|
||
**CRITICO**: GrifoScope invia **datagrammi multi-messaggio**:
|
||
```cpp
|
||
struct b1553_datagram_t {
|
||
uint16_t number_of_messages;
|
||
b1553_raw_message_t msgs[20]; // Fino a 20 messaggi in un frame
|
||
};
|
||
```
|
||
|
||
#### **Trasmissione Ciclica** (`doWork()`)
|
||
```cpp
|
||
// Timer a 10 secondi (10000 µs) per invio frame completo
|
||
scheduler->start(10000); // 100 Hz
|
||
|
||
// Ogni ciclo invia TUTTI i messaggi registrati in UN solo UDP datagram
|
||
s.writeDatagram(&msg, sizeof(msg), rtAddress, 50000+1553);
|
||
```
|
||
|
||
**Differenza Critica con PyBusMonitor**:
|
||
- GrifoScope → **1 datagram UDP** con **tutti i messaggi A1-A5** + request B6-B7
|
||
- PyBusMonitor → **multi datagram** (uno per messaggio) con scheduler separato
|
||
|
||
---
|
||
|
||
### 2. **Formato Pacchetto UDP1553** (`udp1553_types.h`, `b1553_udp.cpp`)
|
||
|
||
#### **Header UDP1553** (64 bytes - già implementato ✅)
|
||
```cpp
|
||
struct udp_1553_header_t {
|
||
uint16_t marker1553; // 0x1553
|
||
uint8_t vmajor, vminor; // Version
|
||
uint16_t otype; // 0x4342 ("BC") o 0x5452 ("RT")
|
||
uint8_t ta; // Terminal Address (0=BC, 20=RT)
|
||
uint8_t flags;
|
||
uint32_t fcounter; // Frame counter
|
||
uint32_t mcounter; // Master counter
|
||
// ... altri campi timing/debug
|
||
};
|
||
```
|
||
|
||
#### **Blocco Messaggio** (ripetuto N volte)
|
||
```
|
||
0x3C3C // MARKER_BEGIN
|
||
CW // Command Word (RT, TR, SA, WC)
|
||
SW // Status Word (solo RT replies)
|
||
ERRCODE // Error code
|
||
reserved[2] // 8 bytes reserved
|
||
DATA[wc] // Payload (wc words, Big Endian)
|
||
~CW // Inverted command word
|
||
0x3E3E // MARKER_END
|
||
```
|
||
|
||
#### **Terminatore Frame**
|
||
```
|
||
0x5315 // MARKER_END_1553
|
||
```
|
||
|
||
**⚠️ Problema Rilevato nel Dispatcher**:
|
||
Il parser PyBusMonitor ha già logica per multi-messaggio MA ha bug con terminatori (vedi `dispatcher.py` linee 180-220). GrifoScope usa layout fisso.
|
||
|
||
---
|
||
|
||
### 3. **Sequenza di Startup Radar** (`g346_a1a2.cpp`)
|
||
|
||
GrifoScope implementa sequenza di sicurezza **obbligatoria**:
|
||
|
||
```cpp
|
||
void GrifoMsg_A2B7::startProtection() {
|
||
dSilence.setFromUser(1); // RF SILENCE = ON
|
||
dStby.setFromUser(1); // STANDBY = ON
|
||
}
|
||
```
|
||
|
||
**Workflow Startup** (già parzialmente implementato ✅):
|
||
|
||
| Fase | Durata | STANDBY | SILENCE | Azione |
|
||
|------|--------|---------|---------|--------|
|
||
| **1 - Protection** | 2-3 cicli | ON | ON | Stato sicuro, radar non risponde |
|
||
| **2 - Activation** | 1 ciclo | OFF | OFF | Comando attivazione |
|
||
| **3 - Transition** | 6 cicli (~240ms) | OFF | OFF | Radar elabora cambio modo |
|
||
| **4 - Operational** | continuo | OFF | OFF | Monitoraggio B7 `transition_status` |
|
||
|
||
**Implementazione Python**: Vedi `RadarController.apply_startup_sequence()` - **già corretto** ✅
|
||
|
||
---
|
||
|
||
### 4. **Gestione Request/Reply** (`b1553_udp.cpp`)
|
||
|
||
GrifoScope usa pattern **request-response**:
|
||
|
||
```cpp
|
||
// INVIO (BC → RT):
|
||
// - A1-A5: Comandi con tr=0, payload pieno
|
||
// - B6-B7: Richieste con tr=1, payload vuoto (solo CW)
|
||
|
||
// RICEZIONE (RT → BC):
|
||
// Radar risponde con stesso SA, tr=1, payload pieno
|
||
if (cw.str.tr == 1) { // RT→BC reply
|
||
// Copia dati nel buffer locale
|
||
memcpy(local_buffer[sa], data, wc*2);
|
||
}
|
||
```
|
||
|
||
**Ciclo Tipico**:
|
||
1. GrifoScope invia frame con A1-A5 (comandi) + B6-B7 (request vuote)
|
||
2. Radar risponde con frame separato contenente B6-B7 (dati pieni)
|
||
3. GrifoScope aggiorna display con tellback B7
|
||
|
||
**PyBusMonitor Status**:
|
||
- ✅ Invia A-messages (comandi)
|
||
- ⚠️ Invia B-requests MA non usa formato corretto (vedi sotto)
|
||
|
||
---
|
||
|
||
## 🔧 Differenze Critiche da Risolvere
|
||
|
||
**Riepilogo**:
|
||
- ❌ **2 problemi CRITICI** da risolvere (Multi-Message, B-Request)
|
||
- ✅ **3 aspetti già corretti** (Porte, Endianness, Startup)
|
||
|
||
---
|
||
|
||
### ❌ **PROBLEMA 1: Formato Multi-Messaggio**
|
||
|
||
**GrifoScope**:
|
||
```
|
||
UDP Header (64 bytes)
|
||
↓
|
||
0x3C3C | CW_A1 | ... | DATA_A1[32] | ~CW_A1 | 0x3E3E
|
||
0x3C3C | CW_A2 | ... | DATA_A2[32] | ~CW_A2 | 0x3E3E
|
||
0x3C3C | CW_A3 | ... | DATA_A3[32] | ~CW_A3 | 0x3E3E
|
||
0x3C3C | CW_A4 | ... | DATA_A4[32] | ~CW_A4 | 0x3E3E
|
||
0x3C3C | CW_A5 | ... | DATA_A5[32] | ~CW_A5 | 0x3E3E
|
||
0x3C3C | CW_B6 | ... | [EMPTY] | ~CW_B6 | 0x3E3E ← REQUEST
|
||
0x3C3C | CW_B7 | ... | [EMPTY] | ~CW_B7 | 0x3E3E ← REQUEST
|
||
0x5315 (END marker)
|
||
```
|
||
|
||
**PyBusMonitor Attuale** (`scheduler.py`):
|
||
- Invia messaggi A/B in frame separati
|
||
- Usa rate diversi (50Hz, 25Hz, 6.25Hz)
|
||
- Non raggruppa i messaggi
|
||
|
||
**Radar potrebbe aspettarsi frame singolo con tutti i messaggi sincronizzati!**
|
||
|
||
---
|
||
|
||
### ❌ **PROBLEMA 2: B-Messages Request Format**
|
||
|
||
**GrifoScope** per richieste B (RT→BC):
|
||
```cpp
|
||
// B6/B7 request: tr=1, wc=32, payload=0 bytes (solo header)
|
||
addMsg<msg_settings_tellback_t>(15, 1); // SA=15, tr=1, wc=32
|
||
```
|
||
|
||
**PyBusMonitor Attuale**:
|
||
```python
|
||
# B-messages hanno payload pieno (32 words) anche in TX
|
||
self.msg_b7 = msgs.MsgB7() # Crea con _data[32] inizializzato
|
||
```
|
||
|
||
**ERRORE**: B-requests dovrebbero avere:
|
||
- `tr = 1` (RT transmit) ✅
|
||
- `wc = 32` ✅
|
||
- **Payload VUOTO** (0 bytes data) ❌ → **Attualmente 64 bytes**
|
||
|
||
---
|
||
|
||
### ✅ **~~PROBLEMA 3: Porte UDP~~ - RISOLTO**
|
||
|
||
**VERIFICATO**: Le porte sono già correttamente allineate!
|
||
|
||
**GrifoScope**: 60000+1553 = **61553** (RX), 50000+1553 = **51553** (TX)
|
||
**PyBusMonitor**: RX_PORT = **61553**, TARGET_PORT = **51553**
|
||
|
||
✅ **Nessuna modifica necessaria**
|
||
|
||
---
|
||
|
||
### ✅ **~~PROBLEMA 4: Endianness e Bit Numbering~~ - GIÀ CORRETTO**
|
||
|
||
**VERIFICATO**:
|
||
- ✅ Payload: Big Endian (network byte order) - **OK**
|
||
- ✅ Headers: Little Endian - **OK**
|
||
- ✅ Bit numbering: MSB=0 convention - **OK nei field descriptors**
|
||
|
||
**CRITICO da verificare**:
|
||
- Inverted CW (`~cw`) deve usare **bitwise NOT** su 16-bit
|
||
- Alcuni radar potrebbero essere sensibili a byte swap in `~CW`
|
||
|
||
---
|
||
|
||
### ⚠️ **PROBLEMA 5: Porte UDP - FALSO ALLARME** ✅
|
||
|
||
**VERIFICATO**: Le porte sono già allineate correttamente!
|
||
|
||
**Da verificare con test reale**:
|
||
- Inverted CW (`~cw`) usa bitwise NOT su 16-bit (già implementato ✅)
|
||
- Layout terminatore: `inv_cw (LE) → MARKER_END (LE)` (già implementato ✅)
|
||
❌ ~~Discrepanza di 1000 porte~~ → ✅ **IDENTICHE - Nessun problema**
|
||
|
||
---
|
||
|
||
### ⚠️ **PROBLEMA 6: Dispatcher Multi-Message Bug**
|
||
|
||
File `dispatcher.py` linee 180-250 contiene workaround per terminatori:
|
||
|
||
```python
|
||
# Accept if LE matches expected and control marker is correct
|
||
if (inv_cw_le == expected_inv_cw) and (ctrl_le == MARKER_END):
|
||
accepted = True
|
||
# Else try BE, fallback scans, etc...
|
||
```
|
||
|
||
**Issue**: Logica troppo permissiva causa falsi positivi. GrifoScope usa **layout fisso**:
|
||
```
|
||
DATA[wc] → inv_cw (LE) → MARKER_END (LE)
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ Cosa Funziona Già (Non Toccare)
|
||
|
||
1. **Message Definitions** (`lib1553/messages/`) - ✅ Corrette vs C++ ICD
|
||
2. **Field Descriptors** (`fields.py`) - ✅ MSB=0 bit numbering
|
||
3. **PacketBuilder** (`packet_builder.py`) - ✅ UDP1553 header format
|
||
4. **Startup Sequence** (`controller.py`) - ✅ STANDBY/SILENCE phases
|
||
5. **Navigation Data** - ✅ Validity flags (inverse logic)
|
||
|
||
---
|
||
|
||
## 🎯 Piano d'Azione
|
||
|
||
### **FASE 1: Verifica Compatibilità Formato** (Diagnostica)
|
||
|
||
**Obiettivo**: Catturare traffico GrifoScope reale e confrontare con PyBusMonitor
|
||
|
||
#### Task 1.1: Cattura Pacchetti GrifoScope
|
||
```bash
|
||
# Usa Wireshark o tcpdump per catturare:
|
||
# - GrifoScope → Radar (porta 50553)
|
||
# - Radar → GrifoScope (porta 60553)
|
||
|
||
# Salva PCAP e analizza:
|
||
python tools/analyze_wireshark_dump.py grifoscope_capture.pcap
|
||
```
|
||
|
||
**Deliverable**: File con layout esatto frame GrifoScope
|
||
|
||
#### Task 1.2: Confronto Binario
|
||
```python
|
||
# tools/compare_grifoscope_packets.py
|
||
# Compara:
|
||
# - Header fields (fcounter, mcounter, etc.)
|
||
# - Message order (A1-A5, B6-B7)
|
||
# - Word count per messaggio
|
||
# - Payload content (campo per campo)
|
||
```
|
||
|
||
**Deliverable**: Report discrepanze
|
||
|
||
---
|
||
|
||
### **FASE 2: Fix Formato B-Request** (Codice)
|
||
|
||
**Problema**: B-messages inviate con payload pieno invece di vuoto
|
||
|
||
#### Task 2.1: Modificare PacketBuilder
|
||
```python
|
||
# pybusmonitor1553/core/packet_builder.py
|
||
|
||
def build_message_block(self, message, force_empty_payload=False):
|
||
"""
|
||
Args:
|
||
force_empty_payload: Se True, invia solo header senza data
|
||
(usato per B-requests)
|
||
"""
|
||
if force_empty_payload:
|
||
# tr=1, wc=32 MA data_bytes=0
|
||
return header_bytes + inv_cw + marker_end
|
||
else:
|
||
# tr=0 o tr=1 con payload
|
||
return header_bytes + data_bytes + inv_cw + marker_end
|
||
```
|
||
|
||
#### Task 2.2: Flag nelle Message Class
|
||
```python
|
||
# lib1553/message_base.py
|
||
|
||
class MessageBase:
|
||
IS_TRANSMIT = False # Existing
|
||
REQUEST_MODE = False # NEW: True per B-requests (no payload)
|
||
|
||
# lib1553/messages/msg_b7.py
|
||
class MsgB7(MessageBase):
|
||
IS_TRANSMIT = True
|
||
REQUEST_MODE = True # ← B-messages sono requests!
|
||
```
|
||
|
||
**Deliverable**: B-requests inviate con 0 data bytes
|
||
|
||
---
|
||
|
||
### **FASE 3: Implementare Frame Multi-Messaggio** (Architettura)
|
||
|
||
**Problema**: Inviare tutti i messaggi in UN frame come GrifoScope
|
||
|
||
#### Task 3.1: Nuovo Builder Pattern
|
||
```python
|
||
# pybusmonitor1553/core/packet_builder.py
|
||
|
||
def build_multi_message_frame(self, messages):
|
||
"""
|
||
Costruisce frame singolo con N messaggi (stile GrifoScope).
|
||
|
||
Args:
|
||
messages: Lista [MsgA1, MsgA2, ..., MsgB7]
|
||
Returns:
|
||
bytes: UDP datagram completo
|
||
"""
|
||
frame = UDP1553Header(...) # 64 bytes
|
||
|
||
for msg in messages:
|
||
# Determina se request (B-msg) o command (A-msg)
|
||
is_request = getattr(msg, 'REQUEST_MODE', False)
|
||
frame += build_message_block(msg, force_empty_payload=is_request)
|
||
|
||
frame += MARKER_END_1553
|
||
return frame
|
||
```
|
||
|
||
#### Task 3.2: Modificare Scheduler
|
||
```python
|
||
# pybusmonitor1553/core/scheduler.py
|
||
|
||
class TrafficScheduler:
|
||
def __init__(self, controller, network):
|
||
self.mode = 'GRIFOSCOPE' # NEW: 'LEGACY' o 'GRIFOSCOPE'
|
||
|
||
def _schedule_grifoscope_mode(self):
|
||
"""
|
||
Invia frame singolo con tutti i messaggi ogni 40ms (25 Hz).
|
||
"""
|
||
messages = [
|
||
self.controller.msg_a1,
|
||
self.controller.msg_a2,
|
||
self.controller.msg_a3,
|
||
self.controller.msg_a4,
|
||
self.controller.msg_a5,
|
||
self.controller.msg_b6, # Request
|
||
self.controller.msg_b7, # Request
|
||
]
|
||
frame = self.builder.build_multi_message_frame(messages)
|
||
self.network.send(frame, self.target_ip, self.target_port)
|
||
```
|
||
|
||
**Deliverable**: Modalità compatibile GrifoScope attivabile via flag
|
||
|
||
---
|
||
|
||
### **FASE 4: Fix Dispatcher Multi-Message** (Parser)
|
||
|
||
**Problema**: Parser troppo permissivo con terminatori
|
||
|
||
#### Task 4.1: Semplificare Logica
|
||
```python
|
||
# pybusmonitor1553/core/dispatcher.py
|
||
|
||
def parse_packet(self, raw_data):
|
||
# REMOVE: Fallback scans, BE/LE alternation
|
||
# USE: Strict layout matching GrifoScope
|
||
|
||
# Expected: DATA → inv_cw (LE) → MARKER_END (LE)
|
||
inv_cw, ctrl_marker = struct.unpack_from('<HH', raw_data, offset)
|
||
|
||
if inv_cw != expected_inv_cw:
|
||
raise ValueError(f"Invalid ~CW at offset {offset}")
|
||
if ctrl_marker != MARKER_END:
|
||
raise ValueError(f"Invalid MARKER_END at offset {offset}")
|
||
```Network Configuration** (Config) - ✅ OPZIONALE
|
||
|
||
#### Task 5.1: ~~Porte UDP~~ - GIÀ CORRETTE ✅
|
||
Le porte sono identiche a GrifoScope. Nessuna modifica necessaria.
|
||
|
||
#### Task 5.2: Broadcast vs Unicast (Opzionale)
|
||
```python
|
||
# Verificare con test reale se radar richiede broadcast
|
||
# GrifoScope usa: rtAddress = networkBroadcast()
|
||
# Può essere 127.0.0.255 (broadcast) o 127.0.0.1 (unicast)
|
||
|
||
BROADCAST_MODE = os.getenv('PYBM_BROADCAST', 'false').lower() == 'true'
|
||
|
||
if BROADCAST_MODE:
|
||
TARGET_IP = "127.0.0.255" # Broadcast locale
|
||
else:
|
||
TARGET_IP = "127.0.0.1" # Unicast (default attuale)
|
||
```
|
||
|
||
**Deliverable**: Test con radar reale determinerà necessità
|
||
TARGET_IP = "127.0.0.255" # Broadcast locale
|
||
else:
|
||
TARGET_IP = "127.0.0.1"
|
||
```
|
||
|
||
**Deliverable**: Flag ambiente per compatibilità totale
|
||
|
||
---
|
||
|
||
### **FASE 6: Testing con Radar Reale** (Validazione)
|
||
|
||
#### Task 6.1: Test di Connessione
|
||
```bash
|
||
# 1. Stop GrifoScope
|
||
# 2. Avvia PyBusMonitor in GRIFOSCOPE_MODE
|
||
export PYBM_GRIFOSCOPE_MODE=true
|
||
python -m pybusmonitor1553
|
||
|
||
# 3. Verifica:
|
||
# - Radar risponde con B-messages?
|
||
# - Transition status in B7 arriva a OPERATIONAL?
|
||
# - Display radar mostra parametri corretti?
|
||
```
|
||
|
||
#### Task 6.2: Confronto Comportamentale
|
||
| Metrica | GrifoScope | PyBusMonitor | Status |
|
||
|---------|-----------|--------------|--------|
|
||
| Radar risponde | ✅ SI | ❓ DA VERIFICARE | |
|
||
| B7 transition complete | ✅ 6 cicli | ❓ DA VERIFICARE | |
|
||
| Parametri radar aggiornati | ✅ SI | ❓ DA VERIFICARE | |
|
||
| Frame rate | 100 Hz | 25 Hz → 100 Hz | TODO |
|
||
|
||
**Deliverable**: Report test con radar vivo
|
||
|
||
---
|
||
|
||
## 📁 Struttura Modifiche al Codice
|
||
|
||
```
|
||
pybusmonitor1553/
|
||
├── core/
|
||
│ ├── packet_builder.py # ✏️ MODIFY: Multi-message frame
|
||
│ ├── scheduler.py # ✏️ MODIFY: GRIFOSCOPE mode
|
||
│ ├── dispatcher.py # ✏️ FIX: Strict terminator parsing
|
||
│ └── controller.py # ✅ OK (startup sequence già corretto)
|
||
├── lib1553/
|
||
│ ├── message_base.py # ✏️ ADD: REQUEST_MODE flag
|
||
│ └── messages/
|
||
│ ├── msg_b*.py # ✏️ SET: REQUEST_MODE = True
|
||
└── __main__.py # ✏️ ADD: GRIFOSCOPE_MODE env var
|
||
|
||
tools/
|
||
├── compare_grifoscope_packets.py # 🆕 NEW: Binary comparison
|
||
├── analyze_wireshark_dump.py # 🆕 NEW: PCAP parser
|
||
└── simple_rt_responder.py # ✅ OK (test tool)
|
||
|
||
doc/
|
||
└── GrifoScope-Migration-Plan.md # 📄 THIS FILE
|
||
```
|
||
|
||
---
|
||
|
||
## 🚦 Roadmap Implementazione
|
||
|
||
### **Sprint 1 (Settimana 1): Diagnostica**
|
||
- [ ] Cattura traffico GrifoScope con Wireshark
|
||
- [ ] Analizza formato esatto frame
|
||
- [ ] Identifica differenze vs PyBusMonitor
|
||
- [ ] Scrivi tool `compare_grifoscope_packets.py`
|
||
|
||
### **Sprint 2 (Settimana 2): Fix Formato**
|
||
- [ ] Implementa `REQUEST_MODE` flag
|
||
- [ ] Modifica `PacketBuilder.build_message_block()`
|
||
- [ ] Test con `simple_rt_responder.py`
|
||
- [ ] Verifica B-requests inviate senza payload
|
||
|
||
### **Sprint 3 (Settimana 3): Multi-Message**
|
||
- [ ] Implementa `build_multi_message_frame()`
|
||
- [ ] Aggiungi `GRIFOSCOPE` mode a scheduler
|
||
- [ ] Test frame rate (25 Hz vs 100 Hz)
|
||
- [ ] Benchmark performance
|
||
|
||
### **Sprint 4 (Settimana 4): Integration**
|
||
- [ ] Fix dispatcher strict parsing
|
||
- [ ] Allinea porte (60553/50553)
|
||
- [ ] Test con radar simulato
|
||
- [ ] ⭐ **TEST CON RADAR REALE**
|
||
|
||
### **Sprint 5 (Settimana 5): Hardening**
|
||
- [ ] Handle edge cases (timeout, packet loss)
|
||
- [ ] Logging migliorato per debug
|
||
- [ ] Documentazione operativa
|
||
- [ ] Training team su modalità GrifoScope
|
||
|
||
---
|
||
|
||
## ⚠️ Rischi e Mitigazioni
|
||
|
||
| Rischio | Probabilità | Impatto | Mitigazione |
|
||
|---------|-------------|---------|-------------|
|
||
| Radar hardcoded su porte GrifoScope | Alta | Alto | Usare stesse porte in GRIFOSCOPE_MODE |
|
||
| Frame format incompatibile | Media | Alto | Cattura PCAP prima di modifiche |
|
||
| ~~Porte UDP diverse~~ | ✅ RISOLTO | - | Porte già allineate (61553/51553) |
|
||
| Frame format incompatibile | Media | Alto | Cattura PCAP prima di modifiche |
|
||
| Timing critico (100 Hz) | Media | Medio | Benchmark Python threading performance |
|
||
| Radar richiede broadcast IP | Bassa | Medio | Test con 127.0.0.255 vs 127.0.0.1 |
|
||
| Radar richiede checksum/CRC | Bassa | Alto | Analizza header `errcode` field
|
||
|
||
## 📊 Metriche di Successo
|
||
|
||
### **Criteri di Accettazione**
|
||
|
||
✅ **MUST HAVE**:
|
||
1. Radar risponde ai comandi A-messages
|
||
2. Radar invia B-messages di tellback
|
||
3. Transition status raggiunge OPERATIONAL
|
||
4. Zero crash o errori di parsing
|
||
|
||
✅ **SHOULD HAVE**:
|
||
5. Frame rate = 100 Hz (come GrifoScope)
|
||
6. Latenza < 10ms per ciclo
|
||
7. Compatibilità backward con modalità legacy
|
||
|
||
✅ **NICE TO HAVE**:
|
||
8. GUI mostra differenze GrifoScope vs PyBusMonitor
|
||
9. Tool di diagnostica automatico
|
||
10. Documentazione completa workflow
|
||
|
||
---
|
||
|
||
## 🔗 Riferimenti
|
||
|
||
### **File Chiave C++**
|
||
- `cpp/GrifoScope/GrifoScope/QgExt/qg1553overudp.cpp` - Logica trasmissione
|
||
- `cpp/GrifoScope/GrifoSdkEif/dev/Portable/ext/b1553_udp.cpp` - Parser radar-side
|
||
- `cpp/GrifoScope/GrifoMCS/GADS/MCS/MCS_G346/g346/g346_a1a2.cpp` - Startup sequence
|
||
|
||
### **File Chiave Python**
|
||
- `pybusmonitor1553/core/dispatcher.py` - Parser UDP1553
|
||
- `pybusmonitor1553/core/packet_builder.py` - Builder frame
|
||
- `pybusmonitor1553/core/scheduler.py` - Timing messaggi
|
||
- `pybusmonitor1553/core/controller.py` - Startup radar
|
||
|
||
### **Documentazione**
|
||
- `doc/ICD-Implementation-Notes.md` - Discrepanze ICD vs C++
|
||
- `doc/Technical-Architecture.md` - Architettura sistema
|
||
- `.github/copilot-instructions.md` - Regole sviluppo
|
||
|
||
---
|
||
|
||
## 🎓 Note per il Team
|
||
|
||
### **Approccio Incrementale**
|
||
1. **Non stravolgere l'architettura esistente** - Aggiungi modalità compatibilità
|
||
2. **Mantieni backward compatibility** - Flag `GRIFOSCOPE_MODE` opzionale
|
||
3. **Test continuo** - Ogni modifica deve passare pytest + test manuale
|
||
4. **Cattura prima, modifica dopo** - PCAP è la fonte di verità
|
||
|
||
### **Debug Tips**
|
||
```bash
|
||
# Abilita logging verbose
|
||
export PYBM_LOG_LEVEL=DEBUG
|
||
|
||
# Cattura pacchetti in tempo reale
|
||
python tools/network_sniffer.py --source python --debug
|
||
|
||
# Confronta con GrifoScope
|
||
diff captured_a_messages_commands_grifoscope.txt \
|
||
captured_a_messages_commands_python.txt
|
||
```
|
||
|
||
### **Quando Chiamare Aiuto**
|
||
- ❌ Radar non risponde dopo 3 cicli di debug
|
||
- ❌ Crash sistematico su parse multi-message
|
||
- ❌ Performance < 25 Hz su hardware target
|
||
- ❌ Discrepanze ICD non documentate nel C++
|
||
|
||
---
|
||
|
||
## ✨ Conclusioni
|
||
|
||
**Status Attuale**: PyBusMonitor ha ~80% delle funzionalità necessarie.
|
||
|
||
**Gap Principali**:
|
||
1. ❌ Frame multi-messaggio (vs singoli datagram)
|
||
2. ❌ B-requests con payload vuoto
|
||
3. ⚠️ Porte UDP diverse
|
||
|
||
**Effort Stimato**:
|
||
- Fase 1-2: 1 settimana (diagnostica **85%** delle funzionalità necessarie.
|
||
|
||
**Gap Principali** (solo 2!):
|
||
1. ❌ Frame multi-messaggio (vs singoli datagram)
|
||
2. ❌ B-requests con payload vuoto
|
||
|
||
**Già Corretti** ✅:
|
||
- ✅ Porte UDP (61553/51553 come GrifoScope)
|
||
- ✅ Endianness (Big Endian payload, Little Endian header)
|
||
- ✅ Startup sequence (STANDBY/SILENCE)
|
||
- ✅ Field descriptors (MSB=0 bit numbering)
|
||
|
||
**Effort Stimato** (rivisto):
|
||
- Fase 1-2: 1 settimana (diagnostica + B-request fix)
|
||
- Fase 3-4: 1.5 settimane (multi-message + dispatcher)
|
||
- Fase 5-6: 0.5 settimane (test radar + validazione)
|
||
|
||
**Total**: ~**3 settimane** per compatibilità completa ⚡
|
||
|
||
**Priorità**:
|
||
1. **CRITICA** - B-request format (blocca risposte radar)
|
||
2. **ALTA** - Multi-message frame (timing/formato)
|
||
3. **MEDIA** - Dispatcher cleanup (funziona ma migliorabile)
|
||
4. **BASSA** - Broadcast IP (test opziona
|
||
|
||
**Domande?** → Apri issue su GitHub o discuti con team lead.
|
||
|
||
---
|
||
|
||
*Documento creato: 2025-12-15*
|
||
*Versione: 1.0*
|
||
*Autore: AI Assistant + Team PyBusMonitor*
|