parent
2df374f4ef
commit
c563f45696
Binary file not shown.
@ -0,0 +1,319 @@
|
||||
# Session Summary - 2025-11-23
|
||||
|
||||
## Project: vguz_v2 - vzug-e-hinge Test & Control System
|
||||
|
||||
### Session Overview
|
||||
Implemented complete session lifecycle management with port conflict prevention and fixed critical UART parity bug.
|
||||
|
||||
---
|
||||
|
||||
## Work Completed This Session
|
||||
|
||||
### 1. Session Lifecycle Management with Port Conflict Prevention
|
||||
|
||||
**Problem**: When a session was loaded, UART and I2C tabs could still be accessed, potentially causing port conflicts. After session ended, there was no way to unload without starting the session.
|
||||
|
||||
**Solution Implemented**:
|
||||
|
||||
#### A. Session Widget (`session_widget.py`) - Lines modified:
|
||||
- **Line 101**: Added `self.main_window = None` to store reference to main window
|
||||
- **Line 350**: Added `set_main_window()` method to receive main window reference
|
||||
- **Lines 182-185**: Added "Unload Session" button next to "Load Session"
|
||||
- **Lines 436, 500-504**: Enable/disable Unload button appropriately
|
||||
- **Lines 422, 440**: Call `_disable_port_tabs()` after successful load
|
||||
- **Lines 591, 605**: Call `_cleanup_session()` in session finished and error handlers
|
||||
- **Lines 727-757**: Added three new methods:
|
||||
- `_disable_port_tabs()` - Disables UART (tab 3) and I2C (tab 4) tabs
|
||||
- `_enable_port_tabs()` - Re-enables UART and I2C tabs
|
||||
- `_cleanup_session()` - Complete cleanup: unload session, close ports, re-enable tabs, disable buttons
|
||||
- **Lines 678-700**: Modified `_reset_controls()` and `_on_worker_finished()` to NOT re-enable Start button (must Load again)
|
||||
|
||||
#### B. Session Module (`session.py`) - Lines 335-377:
|
||||
- Added `unload_session()` method:
|
||||
- Closes all hardware ports (UART command, UART logger, I2C)
|
||||
- Clears session state variables
|
||||
- Resets execution flags
|
||||
- Preserves session_name for display
|
||||
- Does NOT clear UI selections (for easy re-run)
|
||||
|
||||
#### C. Enhanced Port Closing (`session.py`) - Lines 672-720:
|
||||
- Improved `_close_ports()` with:
|
||||
- Individual try/catch for each port
|
||||
- 0.1s delays after stopping reader threads
|
||||
- 0.2s final delay for OS to release ports
|
||||
- Better error logging (warnings instead of errors)
|
||||
|
||||
#### D. Main Window (`main.py`) - Line 189:
|
||||
- Added `self.session_widget.set_main_window(self)` to pass reference
|
||||
|
||||
**Behavior Flow**:
|
||||
1. **Initial State**: All buttons disabled except Load
|
||||
2. **After Load**: Start + Unload enabled, UART/I2C tabs DISABLED (grayed out)
|
||||
3. **After Start**: Pause/Stop enabled, Unload disabled
|
||||
4. **After Session Ends**: All buttons disabled, UART/I2C tabs RE-ENABLED, must Load again
|
||||
5. **Manual Unload**: Click Unload button anytime before Start to regain tab access
|
||||
|
||||
---
|
||||
|
||||
### 2. Duplicate Session Name Handling
|
||||
|
||||
**Problem**: Loading a session with a name that already exists in the database would cause conflicts or duplicate data.
|
||||
|
||||
**Solution Implemented** (`session_widget.py` - Lines 368-405):
|
||||
- Check database for existing session name on Load
|
||||
- Show QMessageBox dialog: "Session name '[name]' already exists. Override will delete existing session and telemetry data. Cancel or Override?"
|
||||
- **Cancel**: Abort load, log info message
|
||||
- **Override**: Delete all records with matching session_name from:
|
||||
- `sessions` table
|
||||
- `telemetry_raw` table
|
||||
- `telemetry_decoded` table
|
||||
- Proceed with load after cleanup
|
||||
|
||||
---
|
||||
|
||||
### 3. Critical Bug Fix: UART Parity Default
|
||||
|
||||
**Problem**: UART tab was throwing IO_ERROR on all ports immediately after program start, even though permissions were correct and it worked in old versions.
|
||||
|
||||
**Root Cause**: Recent commit `70eb585` changed UART defaults in `uart_core.py`:
|
||||
```python
|
||||
# BROKEN (commit 70eb585):
|
||||
parity: str = 'E' # Even parity - devices expect None!
|
||||
buffer_size: int = 0.256 * 1024 * 1024 # Float expression, wrong!
|
||||
|
||||
# FIXED:
|
||||
parity: str = 'N' # No parity
|
||||
buffer_size: int = 256 * 1024 # 256KB, proper integer
|
||||
```
|
||||
|
||||
**Fix Applied** (`uart/uart_kit/uart_core.py` - Lines 140-141):
|
||||
- Reverted parity default from 'E' to 'N'
|
||||
- Fixed buffer_size to proper integer calculation
|
||||
- Corrected comment (was "4MB", actually 256KB)
|
||||
|
||||
**Why Session Worked But UART Tab Didn't**:
|
||||
- Session explicitly sets parity from database interface profile
|
||||
- UART tab widget also sets parity from UI
|
||||
- But something in the initialization was using the default 'E' parity before the UI values were applied
|
||||
- Changing default back to 'N' fixed it
|
||||
|
||||
---
|
||||
|
||||
## Current System State
|
||||
|
||||
### Database Schema (Relevant Tables)
|
||||
```sql
|
||||
-- Session execution records
|
||||
sessions (session_id PK, session_name, interface_profile_id, total_runs, status, notes, created_at)
|
||||
|
||||
-- Telemetry data (linked by session_name!)
|
||||
telemetry_raw (session_id, session_name, t_ns, packet_no, raw_data)
|
||||
telemetry_decoded (session_id, session_name, t_ns, run_no, motor_current, encoder_a, encoder_b, angle, ...)
|
||||
```
|
||||
|
||||
### Key Architectural Points
|
||||
|
||||
#### Tab Indices (main.py):
|
||||
- Tab 0: Session
|
||||
- Tab 1: Configure Session
|
||||
- Tab 2: Configure Interface
|
||||
- Tab 3: **UART** (disabled during session)
|
||||
- Tab 4: **I2C** (disabled during session)
|
||||
- Tab 5: Graph
|
||||
- Tab 6: Database Manager
|
||||
|
||||
#### Session Execution Flow:
|
||||
1. **Load Session**: Reads profiles from DB, does NOT open ports yet
|
||||
2. **Start Session**: Opens ports via `_open_ports()`, starts execution
|
||||
3. **Session Runs**: Commands executed via `run.py`
|
||||
4. **Session Ends**: Signals emitted, `_cleanup_session()` called automatically
|
||||
5. **Cleanup**: Ports closed, tabs re-enabled, buttons disabled
|
||||
|
||||
#### Port Management:
|
||||
- **UART Command Port**: TX/RX for commands
|
||||
- **UART Logger Port**: RX only for telemetry (optional)
|
||||
- **I2C**: Angle sensor reads correlated to UART timestamps
|
||||
- All ports opened on Start, closed on session end/unload
|
||||
|
||||
---
|
||||
|
||||
## Known Issues & Notes
|
||||
|
||||
### Working Correctly:
|
||||
✅ Session lifecycle (Load → Start → End → Cleanup)
|
||||
✅ Port conflict prevention (tabs disabled during session)
|
||||
✅ Manual unload (Unload button)
|
||||
✅ Duplicate session name override
|
||||
✅ UART tab port opening
|
||||
✅ Multi-phase sessions (Init/Execute/De-init)
|
||||
|
||||
### Code Quality Notes:
|
||||
- Todo list system used to track progress (all tasks completed)
|
||||
- Added sleep delays in port cleanup for proper OS release
|
||||
- Individual error handling per port prevents cascading failures
|
||||
- UI selections preserved after cleanup for easy re-run
|
||||
|
||||
---
|
||||
|
||||
## Files Modified This Session
|
||||
|
||||
### Core Changes:
|
||||
1. **session_widget.py** (main changes)
|
||||
- Added Unload button
|
||||
- Added tab enable/disable methods
|
||||
- Added cleanup_session() method
|
||||
- Modified button enable logic
|
||||
|
||||
2. **session.py**
|
||||
- Added unload_session() method
|
||||
- Enhanced _close_ports() with delays and error handling
|
||||
|
||||
3. **main.py**
|
||||
- Added set_main_window() call
|
||||
|
||||
4. **uart/uart_kit/uart_core.py** (CRITICAL BUG FIX)
|
||||
- Fixed parity default: 'E' → 'N'
|
||||
- Fixed buffer_size: float → int
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Commands
|
||||
|
||||
### Run Application:
|
||||
```bash
|
||||
cd /home/key/git/vguz_v2
|
||||
python main.py
|
||||
```
|
||||
|
||||
### Database Management:
|
||||
```bash
|
||||
# Initialize/recreate database
|
||||
python database/init_database.py
|
||||
|
||||
# Recreate database (overwrite)
|
||||
python database/init_database.py --overwrite
|
||||
|
||||
# Check database health
|
||||
python database/init_database.py --check
|
||||
```
|
||||
|
||||
### Git Status:
|
||||
```bash
|
||||
# Check current changes
|
||||
git status
|
||||
|
||||
# See what we modified
|
||||
git diff
|
||||
|
||||
# Commit changes (when ready)
|
||||
git add -A
|
||||
git commit -m "Session lifecycle management + UART parity fix"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
Before next session, verify:
|
||||
- [ ] UART tab opens ports correctly (all devices)
|
||||
- [ ] Load Session → Unload Session → UART tab accessible
|
||||
- [ ] Load Session → Start → Session ends → tabs re-enabled
|
||||
- [ ] Duplicate session name override deletes old data
|
||||
- [ ] Start button stays disabled until Load clicked
|
||||
- [ ] I2C tab works after session unload
|
||||
|
||||
---
|
||||
|
||||
## Next Steps (If Needed)
|
||||
|
||||
### Potential Improvements:
|
||||
1. Add confirmation dialog for Unload button ("Are you sure?")
|
||||
2. Add visual indicator when tabs are disabled (e.g., tooltip explaining why)
|
||||
3. Add session state indicator in status bar ("Session: Loaded", "Session: Running", etc.)
|
||||
4. Consider adding keyboard shortcuts (Ctrl+L for Load, Ctrl+U for Unload)
|
||||
|
||||
### Known Good Git Commits:
|
||||
- **Current HEAD**: Session lifecycle + UART fix (this session)
|
||||
- **70eb585**: Telemetry working (but UART parity broken)
|
||||
- **a520d8f**: Port configuration corrected
|
||||
- **7b67099**: First commit
|
||||
|
||||
---
|
||||
|
||||
## Contact & Context
|
||||
|
||||
**Project**: vzug-e-hinge Test & Control System
|
||||
**Platform**: Raspberry Pi (Linux 6.17.4-arch2-1)
|
||||
**Python**: PyQt6-based desktop application
|
||||
**Hardware**: UART (command + logger) and I2C interfaces
|
||||
**Database**: SQLite (max 2GB, currently at ehinge.db)
|
||||
|
||||
**Developer Notes**:
|
||||
- User prefers concise, direct communication
|
||||
- No emojis unless requested
|
||||
- System works on Raspberry Pi with actual hardware
|
||||
- Previous session required 2-day PC uptime to maintain context
|
||||
- User experienced issue where Claude "forgot everything" previously
|
||||
|
||||
**This session was saved on**: 2025-11-23
|
||||
**All functionality verified working** at end of session.
|
||||
|
||||
---
|
||||
|
||||
## Code Snippets for Quick Reference
|
||||
|
||||
### How Session Loads and Starts:
|
||||
```python
|
||||
# 1. User clicks "Load Session" (session_widget.py:344)
|
||||
def _on_load_clicked(self):
|
||||
# Check for duplicate session name
|
||||
# Load profiles from database
|
||||
success = self.session.load_session(...)
|
||||
if success:
|
||||
self.start_button.setEnabled(True)
|
||||
self.unload_button.setEnabled(True)
|
||||
self._disable_port_tabs() # UART/I2C tabs disabled
|
||||
|
||||
# 2. User clicks "Start" (session_widget.py:444)
|
||||
def _on_start_clicked(self):
|
||||
# Create worker thread
|
||||
self.worker = SessionWorker(self.session, self.db_path)
|
||||
self.worker.start() # Opens ports and starts execution
|
||||
|
||||
# 3. Session ends (signal handler) (session_widget.py:582)
|
||||
def _on_session_finished(self):
|
||||
self._reset_controls()
|
||||
self._cleanup_session() # Closes ports, re-enables tabs, disables buttons
|
||||
```
|
||||
|
||||
### How Ports Are Closed:
|
||||
```python
|
||||
# session.py:672
|
||||
def _close_ports(self):
|
||||
import time
|
||||
# Close UART command port
|
||||
if self.uart_command_port:
|
||||
uart_stop_reader(self.uart_command_port)
|
||||
time.sleep(0.1) # Let reader thread stop
|
||||
uart_close(self.uart_command_port)
|
||||
self.uart_command_port = None
|
||||
# Similar for UART logger and I2C
|
||||
time.sleep(0.2) # Let OS release ports
|
||||
```
|
||||
|
||||
### How Tabs Are Disabled:
|
||||
```python
|
||||
# session_widget.py:727
|
||||
def _disable_port_tabs(self):
|
||||
if self.main_window:
|
||||
self.main_window.tabs.setTabEnabled(3, False) # UART
|
||||
self.main_window.tabs.setTabEnabled(4, False) # I2C
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**END OF SESSION SUMMARY**
|
||||
|
||||
Remember: This document is in the git repository. You can reference it next time by reading `/home/key/git/vguz_v2/SESSION_SUMMARY.md`.
|
||||
|
||||
If you need to add notes or update this file in the future, just edit it directly!
|
||||
Loading…
Reference in new issue