# Message Field Inspector - Documentazione ## Panoramica Sistema per l'ispezione ed export dei metadati dei campi dei messaggi MIL-STD-1553. Estrae automaticamente per ogni campo: - **Name**: Nome completo del campo (es: `RDROperationalSettings.spare`) - **Offset**: Indice della word nel messaggio (0-based) - **OffsetValue**: Bit di partenza nella word (LSB = 0) - **Width**: Numero di bit occupati dal campo - **Type**: Tipo del campo (`bitfield`, `uint16`, `structure`, etc.) - **EnumType**: Nome del tipo enum se applicabile --- ## File Creati ### 1. `message_inspector.py` Modulo principale con le classi: - **`FieldMetadata`**: Rappresenta i metadati di un singolo campo - **`MessageInspector`**: Ispeziona strutture `ctypes` ed estrae metadati - **`inspect_all_messages()`**: Ispeziona tutti i messaggi del sistema ### 2. `tools/export_message_fields.py` Script standalone per export completo di tutti i messaggi in formati JSON e XML. **Uso:** ```bash python tools/export_message_fields.py ``` **Output generati:** - `message_fields_export.json`: JSON con tutti i messaggi - `message_fields_xml/*.xml`: File XML separati per ogni messaggio --- ## Formato Export ### JSON ```json { "A2_MsgRdrOperationCommand": [ { "Name": "RdrModeCommandWord.des_ctrl", "Offset": 0, "OffsetValue": 9, "Width": 3, "Type": "bitfield", "EnumType": "DesignationControl" } ] } ``` ### XML ```xml RdrModeCommandWord.des_ctrl 0 9 3 bitfield DesignationControl ``` --- ## Uso Programmatico ### Esempio 1: Ispezionare un singolo messaggio ```python from Grifo_E_1553lib.messages import MessageInspector from Grifo_E_1553lib.messages.msg_rdr_operation_command import MsgRdrOperationCommand # Ispeziona messaggio A2 fields = MessageInspector.inspect_message(MsgRdrOperationCommand) # Stampa informazioni for field in fields: print(f"{field.name}: Word={field.word_offset}, Bit={field.bit_offset}, Width={field.width}") ``` ### Esempio 2: Export JSON di un messaggio ```python from Grifo_E_1553lib.messages import MessageInspector from Grifo_E_1553lib.messages.msg_rdr_settings_and_parameters import MsgRdrSettingsAndParameters # Ispeziona e converti in JSON fields = MessageInspector.inspect_message(MsgRdrSettingsAndParameters) json_output = MessageInspector.export_to_json(fields) # Salva su file with open('a1_fields.json', 'w') as f: f.write(json_output) ``` ### Esempio 3: Ispezionare tutti i messaggi ```python from Grifo_E_1553lib.messages import inspect_all_messages # Ottieni dizionario di tutti i messaggi all_messages = inspect_all_messages() # Itera sui messaggi for msg_name, fields in all_messages.items(): print(f"\n{msg_name}: {len(fields)} campi") for field in fields: if field.width == 1: # Solo flag (1 bit) print(f" - {field.name}") ``` ### Esempio 4: Filtrare campi per criterio ```python from Grifo_E_1553lib.messages import MessageInspector from Grifo_E_1553lib.messages.msg_rdr_operation_command import MsgRdrOperationCommand fields = MessageInspector.inspect_message(MsgRdrOperationCommand) # Trova tutti i campi enum enum_fields = [f for f in fields if f.enum_type] print(f"Campi con enum: {len(enum_fields)}") # Trova campi nella word 0 word0_fields = [f for f in fields if f.word_offset == 0] print(f"Campi in word 0: {len(word0_fields)}") # Trova campi multi-bit (non flag) multibit_fields = [f for f in fields if f.width > 1] print(f"Campi multi-bit: {len(multibit_fields)}") ``` --- ## Statistiche Export Corrente **Messaggi ispezionati**: 11 - A1_MsgRdrSettingsAndParameters (38 campi) - A2_MsgRdrOperationCommand (24 campi) - A3_MsgGraphicSetting (92 campi) - A4_MsgNavDataAndCursor (54 campi) - A5_MsgInuHighSpeed (24 campi) - A7_Msg1DataLinkTarget (22 campi) - A8_Msg2DataLinkTarget (21 campi) - B4_TrackedTarget02_10 (50 campi) - B5_TrackedTarget01 (80 campi) - B6_MsgRdrSettingsAndParametersTellback (82 campi) - B7_MsgRdrStatusTellback (27 campi) **Totale campi**: 502 --- ## Note Tecniche ### Convenzioni Bit Numbering Il sistema usa la convenzione **Little Endian** di `ctypes`: - **LSB = bit 0** (bit meno significativo) - **MSB = bit 15** (bit più significativo) - I bitfield in `ctypes.LittleEndianStructure` sono numerati sequenzialmente dall'inizio **Esempio:** ```python _fields_ = [ ("field_a", c_uint16, 2), # bit 0-1 ("field_b", c_uint16, 3), # bit 2-4 ("field_c", c_uint16, 11), # bit 5-15 ] ``` ### Word Offset L'offset delle word è **0-based**: - Word 0 = prima word del messaggio - Word 1 = seconda word - etc. Le strutture nested incrementano automaticamente il word offset. ### Limitazioni Attuali - **Solo ctypes.Structure**: supporta solo messaggi basati su `ctypes.Structure/Union` - **Bitfield semplici**: non gestisce bitfield complessi con maschere custom - **Enum mapping**: richiede registrazione in `enum_map.ENUM_MAP` --- ## Integrazione Futura ### GUI Integration Il `MessageInspector` può essere integrato nella GUI per: - Visualizzazione dettagli campo al click - Tooltip con metadati campo - Esportazione dinamica messaggi ### Versioning ICD Con la struttura v1/v2 in preparazione, l'inspector potrà: - Comparare campi tra versioni - Identificare differenze automaticamente - Validare compatibilità binaria ### Testing Può essere usato per: - Generare test di pack/unpack automatici - Verificare dimensioni messaggi - Validare mapping ICD vs implementazione --- ## API Reference ### `FieldMetadata` ```python class FieldMetadata: name: str # Nome completo campo word_offset: int # Indice word (0-based) bit_offset: int # Bit di partenza (LSB=0) width: int # Numero bit field_type: str # Tipo campo enum_type: str # Nome enum (optional) def to_dict() -> Dict[str, Any] ``` ### `MessageInspector` ```python class MessageInspector: @staticmethod def inspect_message(message_class) -> List[FieldMetadata] @staticmethod def inspect_structure(structure_class, word_offset=0) -> List[FieldMetadata] @staticmethod def export_to_dict(fields) -> List[Dict[str, Any]] @staticmethod def export_to_json(fields, indent=2) -> str @staticmethod def export_to_xml(fields) -> str ``` ### `inspect_all_messages()` ```python def inspect_all_messages() -> Dict[str, List[FieldMetadata]] ``` Ritorna dizionario con chiave=nome_messaggio, valore=lista_campi. --- ## Esempi Avanzati ### Export CSV Personalizzato ```python import csv from Grifo_E_1553lib.messages import inspect_all_messages all_messages = inspect_all_messages() with open('fields_export.csv', 'w', newline='') as f: writer = csv.writer(f) writer.writerow(['Message', 'Field', 'Word', 'Bit', 'Width', 'Type']) for msg_name, fields in all_messages.items(): for field in fields: writer.writerow([ msg_name, field.name, field.word_offset, field.bit_offset, field.width, field.field_type ]) ``` ### Comparazione tra Messaggi ```python from Grifo_E_1553lib.messages import MessageInspector from Grifo_E_1553lib.messages.msg_rdr_settings_and_parameters import MsgRdrSettingsAndParameters from Grifo_E_1553lib.messages.msg_rdr_settings_and_parameters_tellback import MsgRdrSettingsAndParametersTellback # Confronta A1 e B6 (dovrebbero essere simili) a1_fields = MessageInspector.inspect_message(MsgRdrSettingsAndParameters) b6_fields = MessageInspector.inspect_message(MsgRdrSettingsAndParametersTellback) print(f"A1: {len(a1_fields)} campi") print(f"B6: {len(b6_fields)} campi") # Trova differenze a1_names = {f.name for f in a1_fields} b6_names = {f.name for f in b6_fields} print(f"\nCampi solo in A1: {a1_names - b6_names}") print(f"Campi solo in B6: {b6_names - a1_names}") ``` --- ## Troubleshooting **Q: I bitfield hanno offset errati?** A: Verifica che la struttura usi `ctypes.LittleEndianStructure` e non `ctypes.BigEndianStructure`. **Q: Enum non vengono rilevati?** A: Controlla che siano registrati in `Grifo_E_1553lib.data_types.enum_map.ENUM_MAP`. **Q: Strutture nested non vengono ispezionate?** A: Verifica che ereditino da `ctypes.Structure` o `ctypes.Union`.