Step 2 - LDF Loading: - ldfparser integration (Python) / custom regex parser (C++) - QTreeWidget with expandable signal rows, merged Value column - Hex/Dec toggle, FreeFormat schedule entries, auto-reload - Baud rate auto-detection from LDF Step 3 - Signal Editing: - Bit packing/unpacking (signal value ↔ frame bytes) - ReadOnlyColumnDelegate for per-column editability - Value clamping to signal width, recursion guard Step 4 - Rx Panel: - receive_rx_frame() API with timestamp, signal unpacking - Change highlighting (yellow), auto-scroll toggle, clear button - Dashboard view (in-place update per frame_id) Step 5 - Connection Panel: - ConnectionManager with state machine (Disconnected/Connecting/Connected/Error) - Port scanning (pyserial / QSerialPort), connect/disconnect with UI mapping Step 6 - BabyLIN Backend: - BabyLinBackend wrapping Lipowsky BabyLIN_library.py DLL - Mock mode for macOS/CI, device scan, SDF loading, signal access - Frame callbacks, raw command access Step 7 - Master Scheduler: - QTimer-based schedule execution with start/stop/pause - Frame sent callback with visual highlighting - Mock Rx simulation, manual send, global rate override Tests: Python 171 | C++ 124 (Steps 1-5 parity, Steps 6-7 Python-first) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
215 lines
8.3 KiB
Markdown
215 lines
8.3 KiB
Markdown
# LIN Master Simulator Tool — Implementation Plan
|
|
|
|
## Context
|
|
Build a cross-platform LIN master simulator GUI using BabyLIN devices. Two parallel implementations: Python (PyQt6) and C++ (Qt6). Each step is built, verified, and tested before moving to the next.
|
|
|
|
## Project Structure
|
|
```
|
|
LIN_Control_Tool/
|
|
├── python/ # Python implementation
|
|
│ ├── src/
|
|
│ ├── tests/
|
|
│ └── requirements.txt
|
|
├── cpp/ # C++ implementation
|
|
│ ├── src/
|
|
│ ├── tests/
|
|
│ └── CMakeLists.txt
|
|
└── resources/ # Shared: sample LDF files, icons, etc.
|
|
```
|
|
|
|
## Tech Stack
|
|
- **Python:** PyQt6, ldfparser, pyserial, pytest
|
|
- **C++:** Qt6 (Widgets, SerialPort), CMake, GoogleTest
|
|
- **LDF parsing (C++):** Custom or port of ldfparser logic
|
|
|
|
## Step-by-Step Plan
|
|
|
|
### Step 1 — GUI Skeleton
|
|
- **Status:** DONE — Python (32/32 tests) | C++ (34/34 tests)
|
|
- **Goal:** Main window with all panel placeholders laid out.
|
|
|
|
**Panels:**
|
|
- Top bar: LDF file loader (path + browse button + auto-reload indicator)
|
|
- Left: Connection status panel (device dropdown, connect/disconnect, status LED)
|
|
- Center-top: Tx panel (table placeholder — frame name, ID, signals, data, send button)
|
|
- Center-bottom: Rx panel (table placeholder — timestamp, frame name, ID, data, signals)
|
|
- Bottom: Control bar (start/stop scheduler, manual send)
|
|
|
|
**Python:** PyQt6 QMainWindow, QDockWidget or QSplitter layout
|
|
**C++:** Qt6 QMainWindow, same layout with .ui or code-based
|
|
|
|
**Testing:**
|
|
- Launch app, verify all panels render correctly
|
|
- Resize window — panels resize proportionally
|
|
- Cross-platform: test on macOS, Windows, Linux
|
|
|
|
---
|
|
|
|
### Step 2 — LDF Loading & Display
|
|
- **Status:** DONE — Python (86 tests) | C++ (91 tests)
|
|
- **Features:** QTreeWidget expandable signals, merged Value column, Hex/Dec toggle, FreeFormat schedule entries, ReadOnlyColumnDelegate, baud rate normalization
|
|
- **Goal:** Load an LDF file, parse it, populate Tx/Rx tables with frame/signal info.
|
|
|
|
**Features:**
|
|
- File picker dialog
|
|
- Parse LDF using `ldfparser` (Python) / custom parser (C++)
|
|
- Populate Tx table with master frames (name, ID, length, signals)
|
|
- Populate Rx table columns (ready for runtime data)
|
|
- Auto-reload: watch file for changes, re-parse on modification
|
|
- Error handling for invalid LDF files
|
|
|
|
**Python:** ldfparser library, QFileSystemWatcher for auto-reload
|
|
**C++:** Custom LDF parser, QFileSystemWatcher
|
|
|
|
**Testing:**
|
|
- Load valid LDF → tables populate correctly
|
|
- Load invalid file → error message shown
|
|
- Modify LDF on disk → auto-reload triggers, tables update
|
|
- Verify parsed frame IDs, signal names, lengths match LDF content
|
|
|
|
---
|
|
|
|
### Step 3 — Tx Panel (Signal Editing)
|
|
- **Status:** DONE — Python (99 tests) | C++ (106 tests)
|
|
- **Features:** Bit packing/unpacking, signal↔frame byte sync, value clamping, hex/dec input support, recursion guard
|
|
- **Goal:** Editable Tx table where user can modify signal values based on LDF types.
|
|
|
|
**Features:**
|
|
- Each master frame row expandable to show individual signals
|
|
- Signal value editors based on type (bool → checkbox, int → spinbox, enum → dropdown)
|
|
- Frame data bytes update live as signals are edited
|
|
- Respect signal bit position, length, encoding from LDF
|
|
- Manual "Send" button per frame
|
|
|
|
**Python:** QTreeWidget or QTableWidget with custom delegates
|
|
**C++:** Same with QStyledItemDelegate subclasses
|
|
|
|
**Testing:**
|
|
- Edit a signal → frame data bytes reflect the change correctly
|
|
- Bool signal toggles between 0/1
|
|
- Enum signal shows correct value names from LDF
|
|
- Integer signal respects min/max range from LDF
|
|
- Bit packing: verify multi-signal frames encode correctly
|
|
|
|
---
|
|
|
|
### Step 4 — Rx Panel (Real-time Display)
|
|
- **Status:** DONE — Python (116 tests) | C++ (124 tests)
|
|
- **Features:** receive_rx_frame API, timestamp updates, signal unpacking, change highlighting (yellow), auto-scroll toggle, clear button, dashboard view (in-place update per frame_id)
|
|
- **Goal:** Rx table that shows incoming frames with timestamps.
|
|
|
|
**Features:**
|
|
- Columns: timestamp, frame name, frame ID, raw data, decoded signals
|
|
- Expandable rows to see individual signal values
|
|
- Auto-scroll with pause option
|
|
- Clear button
|
|
- Signal highlighting on value change
|
|
|
|
**Python:** QTableWidget with QTimer-based mock data for testing
|
|
**C++:** Same approach
|
|
|
|
**Testing:**
|
|
- Feed mock Rx data → rows appear with correct timestamps
|
|
- Auto-scroll follows new data
|
|
- Pause stops scrolling, resume catches up
|
|
- Signal decode matches expected values
|
|
- Performance: handle 1000+ rows without lag
|
|
|
|
---
|
|
|
|
### Step 5 — Connection Panel & Device Discovery
|
|
- **Status:** DONE — Python (133 tests) | C++ (124 tests + connection_manager)
|
|
- **Features:** ConnectionManager with state machine (Disconnected/Connecting/Connected/Error), port scanning (pyserial/QSerialPort), connect/disconnect with UI state mapping, error handling, mock-based testing
|
|
- **Goal:** Detect BabyLIN devices, show connection status.
|
|
|
|
**Features:**
|
|
- Scan for available serial ports / BabyLIN devices
|
|
- Device dropdown with refresh button
|
|
- Connect / Disconnect buttons
|
|
- Status indicator (disconnected/connecting/connected/error)
|
|
- Display device info on connect (firmware version, etc.)
|
|
|
|
**Python:** pyserial for port enumeration, QThread for connection
|
|
**C++:** QSerialPort, QSerialPortInfo
|
|
|
|
**Testing:**
|
|
- No device → dropdown empty, status shows "No device"
|
|
- Mock serial port → connection succeeds, status turns green
|
|
- Disconnect → status updates, UI re-enables connect
|
|
- Unplug during session → error state shown, graceful handling
|
|
|
|
---
|
|
|
|
### Step 6 — BabyLIN Communication Backend
|
|
- **Status:** Python DONE (153 tests) | C++ Pending (needs BabyLIN DLL porting)
|
|
- **Features:** BabyLinBackend wrapping Lipowsky's BabyLIN_library.py DLL, mock mode for macOS/CI, device scan/connect/disconnect, SDF loading, start/stop bus, signal read/write, frame callbacks, raw command access
|
|
- **Note:** BabyLIN DLL only available for Linux/Windows. macOS uses mock mode. C++ version will wrap the same C DLL.
|
|
- **Goal:** Implement the protocol layer for BabyLIN communication.
|
|
|
|
**Features:**
|
|
- Serial protocol commands (init, send frame, receive frame)
|
|
- BabyLIN-DLL/SDK integration if available
|
|
- Abstract interface so serial vs SDK can be swapped
|
|
- Frame send/receive with proper LIN timing
|
|
- Error detection and reporting
|
|
|
|
**Python:** pyserial + threading, abstract base class
|
|
**C++:** QSerialPort, abstract interface class
|
|
|
|
**Testing:**
|
|
- Unit test protocol encoding/decoding
|
|
- Loopback test if hardware available
|
|
- Mock device for CI testing
|
|
- Verify frame timing within LIN spec tolerances
|
|
|
|
---
|
|
|
|
### Step 7 — Master Scheduler
|
|
- **Status:** Python DONE (171 tests) | C++ Not started
|
|
- **Features:** QTimer-based schedule execution, start/stop/pause, frame sent callback with visual highlighting, mock Rx simulation, manual send, global rate override, schedule table switching
|
|
- **Goal:** Periodic frame transmission using LDF schedule tables.
|
|
|
|
**Features:**
|
|
- Parse schedule tables from LDF
|
|
- Run selected schedule with correct timing (slot delays)
|
|
- Start/Stop/Pause controls
|
|
- Visual indication of currently transmitting frame
|
|
- Manual send overrides during schedule execution
|
|
- Schedule table selector dropdown
|
|
|
|
**Python:** QTimer-based scheduler, QThread for timing accuracy
|
|
**C++:** QTimer, dedicated thread
|
|
|
|
**Testing:**
|
|
- Start schedule → frames sent in correct order and timing
|
|
- Stop → transmission halts
|
|
- Manual send during schedule → frame injected correctly
|
|
- Verify slot timing accuracy (within tolerance)
|
|
- Switch schedule tables mid-run
|
|
|
|
---
|
|
|
|
### Step 8 — Integration & End-to-End
|
|
- **Status:** Not started
|
|
- **Goal:** Wire all components together, full workflow testing.
|
|
|
|
**Features:**
|
|
- Load LDF → connect device → start schedule → see Rx responses
|
|
- Edit Tx signals on-the-fly during active schedule
|
|
- Full error handling chain (device disconnect mid-run, etc.)
|
|
- Package as standalone executable (PyInstaller / CMake install)
|
|
|
|
**Testing:**
|
|
- Full workflow with real BabyLIN + LIN slave device
|
|
- Stress test: extended run (hours), verify no memory leaks
|
|
- Cross-platform packaging and launch test
|
|
- Verify all UI states transition correctly
|
|
|
|
---
|
|
|
|
## Verification Checklist (Every Step)
|
|
- [ ] Code review — clean, no warnings
|
|
- [ ] Unit tests pass (pytest / GoogleTest)
|
|
- [ ] Manual GUI test on at least one platform
|
|
- [ ] Both Python and C++ versions reach feature parity
|