SXXXXXXX_PyMsc/.github/copilot-instructions.md
2025-12-10 11:47:46 +01:00

5.2 KiB

Copilot / AI Agent Instructions

Purpose: help an AI coding agent be immediately productive in this repo by documenting project shape, important patterns, and common developer workflows observed in the codebase.

  • Top-level structure: core application is in pymsc/ (Core + GUI). A lightweight demo monitor lives in demo_bus_monitor/. Legacy code and examples are in _old/.

  • How the system is split:

    • pymsc/core: application logic and networking (see app_controller.py). It runs the scheduler, receiver, and exposes go() / stop_sending() semantics.
    • pymsc/gui: Tkinter GUI (main_window.py) that talks to AppController.
    • pymsc/lib1553: message formats, ctypes Structure payloads and structures.py (UDP/1553 wrappers & CommandWord/Udp1553Message).
    • demo_bus_monitor/: minimal listener & tools for manual testing and init scripts (see its README.md).
    • tests/: pytest-based tests (see pytest.ini).
  • Key runtime commands (PowerShell examples):

    • Run GUI app: python -m pymsc
    • Run demo monitor: python -m demo_bus_monitor.monitor --ip 0.0.0.0 --port 61553
    • Send initialization sequence (in separate terminal): python demo_bus_monitor/tools/init_connection.py --ip 127.0.0.1 --listen
    • Run tests: activate venv then pytest or python -m pytest.
  • Message + parsing conventions:

    • Payload types are ctypes.Structure classes in pymsc/lib1553/messages/*. Sizes are critical: decoding compares ctypes.sizeof(payload_cls) against observed payload length.
    • AppController._init_messages() registers messages via BaseMessage(label, payload_cls, sub_addr=sa, frequency=freq, is_transmit=is_tx) and populates AppController.rx_map[sa] = payload_class — add new message types here.
    • Parser expects little-endian fields (see struct.unpack_from('<H', ...)). Markers used: Marker.CTRL_BEGIN, Marker.CTRL_END, Marker.END_1553 from pymsc/lib1553/constants.py.
    • There are two wrapper formats: a short observed 12-byte wrapper and a full Udp1553Message. The receiver validates an inverted-CW (bitwise NOT) present after payload — preserve this check when modifying parser logic.
    • Important quirk: WC (word count) handling uses WC=0 => 0 words (not 32). Keep this behavior for compatibility with captured traces.
  • Runtime behaviour to preserve:

    • Periodic transmissions are NOT automatically sent on registration. initialize_radar() configures messages; AppController.go() flips _sending_enabled to start the scheduler sending frames. Tests and tools rely on this two-step flow.
    • Scheduler uses a software millisecond counter with a 20ms tick (time.sleep(0.02)) and checks mytime % period_ms == 0 to decide sends — keep this when adding periodic messages to match legacy timing.
    • The receiver is performance-sensitive: avoid synchronous file I/O or prints inside the hot loop. Use monitor_queue and MonitorBuffer (see pymsc.core.monitor) to pass decoded entries to GUI or tests.
  • Where to add/extend payloads:

    • Add new message payload ctypes.Structure in pymsc/lib1553/messages/ and update _init_messages() in pymsc/core/app_controller.py to register it (label, payload class, SA).
    • For richer examples, consult _old/Grifo_E_1553lib/messages (legacy reference implementations).
  • Logging and artifacts:

    • AppController writes logs to logs/ (app_debug.log, rx_messages.log, tx_messages.log, udp_raw.log). Tests and debugging expect these files to be created; ensure os.makedirs(logs_dir, exist_ok=True) when changing logging.
  • Tests & quick checks:

    • tests/test_imports.py ensures module importability — run it after renames/refactors.
    • Prefer running a focused test: pytest tests/test_monitor_buffer.py -q to verify monitor buffering without launching GUI.
  • Integration points & network expectations:

    • UDP ports: udp_send_port=51553 (sent to radar), udp_recv_port=61553 (listener). The demo README clarifies which side to bind for BC vs RT.
    • Some tools (demo_bus_monitor/tools/*) emulate the radar init sequence; use them for integration tests instead of connecting to real hardware.
  • Common pitfalls to avoid:

    • Do not add blocking disk I/O / prints inside the receiver or scheduler loops — it causes timing issues.
    • Preserve little-endian parsing and inverted-CW validation; many tests and legacy traces rely on these exact checks.
    • When changing payload sizes or bitfields, update both ctypes definitions and places that compute payload_len (receiver logic in app_controller.py).
  • If you need to change high-risk code (parsing, scheduler, or message definitions):

    • Add unit tests in tests/ covering both short-wrapper and full-wrapper parsing paths (there are existing test data and tests in tests/ and demo_bus_monitor/tests).
    • Run pytest and a targeted integration run of demo_bus_monitor using the init_connection.py tool to validate end-to-end behavior.

If anything above is unclear or you'd like more examples (e.g., a template ctypes.Structure for a new B-message), tell me which area to expand and I will iterate.