SXXXXXXX_PyBusMonitor1553/doc/Message-Field-Inspector.md
2026-01-20 12:31:23 +01:00

8.4 KiB

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:

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

{
  "A2_MsgRdrOperationCommand": [
    {
      "Name": "RdrModeCommandWord.des_ctrl",
      "Offset": 0,
      "OffsetValue": 9,
      "Width": 3,
      "Type": "bitfield",
      "EnumType": "DesignationControl"
    }
  ]
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<Message name="A2_MsgRdrOperationCommand">
  <Fields count="24">
    <Field>
      <Name>RdrModeCommandWord.des_ctrl</Name>
      <Offset>0</Offset>
      <OffsetValue>9</OffsetValue>
      <Width>3</Width>
      <Type>bitfield</Type>
      <EnumType>DesignationControl</EnumType>
    </Field>
  </Fields>
</Message>

Uso Programmatico

Esempio 1: Ispezionare un singolo messaggio

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

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

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

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:

_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

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

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()

def inspect_all_messages() -> Dict[str, List[FieldMetadata]]

Ritorna dizionario con chiave=nome_messaggio, valore=lista_campi.


Esempi Avanzati

Export CSV Personalizzato

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

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.