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 indemo_bus_monitor/. Legacy code and examples are in_old/. -
How the system is split:
pymsc/core: application logic and networking (seeapp_controller.py). It runs the scheduler, receiver, and exposesgo()/stop_sending()semantics.pymsc/gui: Tkinter GUI (main_window.py) that talks toAppController.pymsc/lib1553: message formats, ctypesStructurepayloads andstructures.py(UDP/1553 wrappers &CommandWord/Udp1553Message).demo_bus_monitor/: minimal listener & tools for manual testing and init scripts (see itsREADME.md).tests/: pytest-based tests (seepytest.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
pytestorpython -m pytest.
- Run GUI app:
-
Message + parsing conventions:
- Payload types are
ctypes.Structureclasses inpymsc/lib1553/messages/*. Sizes are critical: decoding comparesctypes.sizeof(payload_cls)against observed payload length. AppController._init_messages()registers messages viaBaseMessage(label, payload_cls, sub_addr=sa, frequency=freq, is_transmit=is_tx)and populatesAppController.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_1553frompymsc/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.
- Payload types are
-
Runtime behaviour to preserve:
- Periodic transmissions are NOT automatically sent on registration.
initialize_radar()configures messages;AppController.go()flips_sending_enabledto 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 checksmytime % period_ms == 0to 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_queueandMonitorBuffer(seepymsc.core.monitor) to pass decoded entries to GUI or tests.
- Periodic transmissions are NOT automatically sent on registration.
-
Where to add/extend payloads:
- Add new message payload
ctypes.Structureinpymsc/lib1553/messages/and update_init_messages()inpymsc/core/app_controller.pyto register it (label, payload class, SA). - For richer examples, consult
_old/Grifo_E_1553lib/messages(legacy reference implementations).
- Add new message payload
-
Logging and artifacts:
AppControllerwrites logs tologs/(app_debug.log,rx_messages.log,tx_messages.log,udp_raw.log). Tests and debugging expect these files to be created; ensureos.makedirs(logs_dir, exist_ok=True)when changing logging.
-
Tests & quick checks:
tests/test_imports.pyensures module importability — run it after renames/refactors.- Prefer running a focused test:
pytest tests/test_monitor_buffer.py -qto 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.
- UDP ports:
-
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
ctypesdefinitions and places that computepayload_len(receiver logic inapp_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 intests/anddemo_bus_monitor/tests). - Run
pytestand a targeted integration run ofdemo_bus_monitorusing theinit_connection.pytool to validate end-to-end behavior.
- Add unit tests in
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.