@@ -84,3 +84,285 @@ The application operates in two modes: Manual and Canned Cycle which can be swit
8484- Manual mode allows electronic leadscrew with configurable pitch ratios
8585- Emergency stop preserves work coordinate system
8686- All measurements displayed in current unit system (mm/inch toggle)
87+
88+ ## CRITICAL: Settings Save System - DO NOT BREAK THIS AGAIN!
89+
90+ The settings save system has been broken multiple times. Follow these rules STRICTLY:
91+
92+ ### Settings Architecture
93+ 1 . ** Single Source of Truth** : All settings are managed in ` elle-frontend/src/composables/useSettings.ts `
94+ 2 . ** Single Save Function** : ONLY use the ` saveSettings() ` function from useSettings.ts
95+ 3 . ** NO Duplicate Save Logic** : Never create alternative save mechanisms in App.vue or elsewhere
96+
97+ ### What NOT to do (these have broken settings multiple times):
98+ 1 . ** NEVER** add ` isQuitting ` checks that prevent saving during app exit
99+ 2 . ** NEVER** create manual save logic in ` quitApplication() ` or other functions
100+ 3 . ** NEVER** use ` JSON.parse(JSON.stringify()) ` on Vue reactive objects - it breaks serialization
101+ 4 . ** NEVER** pass Vue refs directly to the save function - always use ` .value `
102+ 5 . ** NEVER** block ALL saves when validation fails - this prevents any settings from being saved
103+
104+ ### Correct Save Implementation:
105+ ``` typescript
106+ // ✅ CORRECT: Manual serialization of reactive refs
107+ const settingsToSave = {
108+ tools: tools .value .map (tool => ({
109+ id: tool .id ,
110+ offsetX: tool .offsetX ,
111+ offsetZ: tool .offsetZ ,
112+ description: tool .description
113+ })),
114+ currentToolOffsetX: currentToolOffsetX .value ,
115+ currentToolOffsetZ: currentToolOffsetZ .value ,
116+ // ... other settings
117+ }
118+ ```
119+
120+ ### Settings Flow:
121+ 1 . ** Auto-save** : Watcher triggers ` saveSettings() ` on any change
122+ 2 . ** Manual save** : ` quitApplication() ` calls ` saveSettings() ` before exit
123+ 3 . ** Electron IPC** : ` window.settings.save() ` → ` main.ts ` → ` electron-store `
124+ 4 . ** Persistence** : Stored in ` ~/.config/elle-app/appConfig.json `
125+
126+ ### Adding New Settings:
127+ When adding new settings, update EXACTLY these files:
128+ 1 . ` elle-frontend/src/composables/useSettings.ts ` (ref definition, save object, return statement, watcher array)
129+ 2 . ` elle-electron/main.ts ` (getSettings return, saveSettings handler)
130+ 3 . ` elle-electron/electron-store/configuration.ts ` (interface definition)
131+ 4 . ` elle-electron/preload.d.ts ` (type definitions)
132+
133+ ### Testing Settings:
134+ After any settings change:
135+ 1 . Run the app and change tool offsets
136+ 2 . Quit the app normally
137+ 3 . Check ` ~/.config/elle-app/appConfig.json ` contains all expected data
138+ 4 . Restart app and verify settings are loaded correctly
139+
140+ ### Emergency Recovery:
141+ If settings are broken again:
142+ 1 . Check console for "An object could not be cloned" errors
143+ 2 . Verify all reactive refs use ` .value ` in save object
144+ 3 . Remove any ` isQuitting ` or validation blocks
145+ 4 . Use manual object mapping instead of JSON serialization
146+
147+ ## Complete Technical Architecture Guide
148+
149+ ### Core Architecture & Data Flow
150+
151+ ** Three-Layer System:**
152+ ```
153+ Vue Frontend (renderer process) ↔ Electron Main Process ↔ Python HAL Backend ↔ LinuxCNC
154+ ```
155+
156+ ** Communication Patterns:**
157+ - ** Position Updates** : 30Hz HTTP polling via ` /hal/hal_in ` endpoint
158+ - ** Control Commands** : Immediate HTTP PUT requests to ` /hal/hal_out `
159+ - ** Settings** : Electron IPC (` getSettings ` /` saveSettings ` ) → electron-store → JSON file
160+ - ** HAL Management** : IPC channels (` startHAL ` , ` stopHAL ` , ` halStarted ` , ` halStopped ` )
161+
162+ ### Key Components & Responsibilities
163+
164+ ** Vue Component Hierarchy:**
165+ ```
166+ App.vue (Main container - state management, menu switching, HAL coordination)
167+ ├── DRODisplay.vue (Digital readout, position display, unit conversion)
168+ ├── Numpad.vue (Touch-friendly numeric input with decimal handling)
169+ ├── OperationPreview.vue (3D backplot using Three.js/troisjs)
170+ ├── ToolTable.vue (Tool offset editing and selection)
171+ ├── ParameterInput.vue (Reusable input with popover help)
172+ ├── ThreadPresetSelector.vue (Threading presets dialog)
173+ ├── TurningPresetSelector.vue (Turning presets dialog)
174+ └── PitchPresetSelector.vue (Manual pitch selection)
175+ ```
176+
177+ ### Critical APIs & Interfaces
178+
179+ ** HAL REST API Endpoints (Python backend on port 8000):**
180+ ``` typescript
181+ // Position & Status (30Hz polling)
182+ GET / hal / hal_in → {position_x , position_z , position_a , speed_rps , program_running , error_state }
183+
184+ // Control Commands
185+ PUT / hal / hal_out → {enable_x , enable_z , forward_x , forward_z , control_source , ... }
186+
187+ // Canned Cycles
188+ PUT / hal / threading → Execute threading cycle
189+ PUT / hal / threading / generate → Generate G - code for backplot
190+ PUT / hal / turning → Execute turning cycle
191+ PUT / hal / turning / generate → Generate G - code for backplot
192+
193+ // Emergency Controls
194+ PUT / hal / abort → Abort current operation
195+ PUT / hal / estop → Emergency stop
196+ PUT / hal / cleanup → Clean up after cycles
197+ ```
198+
199+ ** Electron IPC Channels:**
200+ ``` typescript
201+ // HAL Management
202+ send (' startHAL' ) → Start LinuxCNC
203+ send (' stopHAL' ) → Stop LinuxCNC
204+ receive (' halStarted' ) → HAL ready signal
205+ receive (' halStopped' ) → HAL shutdown signal
206+
207+ // Settings Persistence
208+ invoke (' getSettings' ) → Load all settings
209+ invoke (' saveSettings' , data ) → Save all settings
210+ ```
211+
212+ ** Key Data Structures:**
213+ ``` typescript
214+ interface Tool {
215+ id: number
216+ offsetX: number // X-axis tool offset
217+ offsetZ: number // Z-axis tool offset
218+ description: string
219+ }
220+
221+ interface HalIn {
222+ position_z: number
223+ position_x: number
224+ position_a: number // Spindle angle
225+ speed_rps: number // Spindle speed
226+ program_running: boolean
227+ error_state: boolean
228+ }
229+ ```
230+
231+ ### State Management Architecture
232+
233+ ** Composable-Based State (No Vuex/Pinia):**
234+ - ** useHAL()** : Real-time position data, HAL communication, jog controls
235+ - ** useSettings()** : Persistent settings, unit conversion, tool management
236+ - ** useCannedCycles()** : Threading/turning parameters, validation, G-code generation
237+ - ** useToolTable()** : Tool offset management and selection
238+
239+ ** Position Calculation System:**
240+ ``` typescript
241+ // Work coordinates = Machine coordinates - Axis offsets + Tool offsets
242+ displayPosition = machinePosition - axisOffset + toolOffset
243+
244+ // Diameter mode: X display = X radius × 2
245+ displayXPos = diameterMode .value ? xpos .value * 2 : xpos .value
246+
247+ // Tool offset application (in useHAL startPoll):
248+ zpos .value = (halIn as any ).position_z - zaxisoffset + toolOffsets .currentToolOffsetZ .value
249+ xpos .value = (halIn as any ).position_x - xaxisoffset + toolOffsets .currentToolOffsetX .value
250+ ```
251+
252+ ** Coordinate System Management:**
253+ - Single work coordinate system shared between manual and canned cycle modes
254+ - Axis offsets managed in HAL composable (` xaxisoffset ` , ` zaxisoffset ` , ` aaxisoffset ` )
255+ - Tool offsets applied separately per tool in position calculations
256+ - Reset position functionality zeroes work coordinates
257+
258+ ### Build & Development Workflow
259+
260+ ** Key Scripts:**
261+ ``` bash
262+ # Development
263+ yarn start # Start frontend dev server + electron app + HAL
264+ yarn serve:front # Frontend dev server only (port 3000)
265+ yarn watch # Watch electron main process
266+
267+ # Production
268+ yarn build # Compile TypeScript
269+ yarn build:front # Build Vue frontend
270+ yarn app:build # Full production build with electron-builder
271+ ```
272+
273+ ** Development vs Production:**
274+ - ** Dev** : Frontend from Vite dev server (localhost:3000), devTools enabled
275+ - ** Prod** : Frontend from ` file:// ` protocol, devTools disabled
276+ - ** HAL URLs** : Auto-detect Electron vs browser for remote development
277+
278+ ### Common Coding Patterns
279+
280+ ** Component Pattern:**
281+ ``` vue
282+ <script setup lang="ts">
283+ // 1. Composable imports at top
284+ import { useHAL } from './composables/useHAL'
285+ import { useSettings } from './composables/useSettings'
286+
287+ // 2. Destructure reactive refs
288+ const { xpos, zpos, startPoll } = useHAL()
289+ const { metric, diameterMode } = useSettings()
290+
291+ // 3. Computed properties for display
292+ const displayValue = computed(() =>
293+ metric.value ? value : value / 25.4
294+ )
295+ </script>
296+ ```
297+
298+ ** Unit Conversion Pattern:**
299+ ``` typescript
300+ // Consistent conversion factor usage
301+ const conversionFactor = toMetric ? 25.4 : 1 / 25.4
302+ value = roundParameterValue (value , conversionFactor )
303+
304+ // Display formatting
305+ const formatValue = (value : number ) =>
306+ metric .value ? value .toFixed (3 ) : (value / 25.4 ).toFixed (4 )
307+ ```
308+
309+ ** Error Handling Pattern:**
310+ ``` typescript
311+ // HAL API calls - graceful degradation
312+ try {
313+ const response = await fetch (url , options )
314+ const result = await response .json ()
315+ return result
316+ } catch {
317+ return {} // Silent failure, return empty object
318+ }
319+ ```
320+
321+ ### Adding New Features - Standard Process
322+
323+ 1 . ** Add state to appropriate composable** (useHAL, useSettings, useCannedCycles)
324+ 2 . ** Add persistence to useSettings** if needed:
325+ - Add ref definition
326+ - Add to save object with manual serialization
327+ - Add to return statement
328+ - Add to watcher array
329+ - Update main.ts IPC handlers
330+ - Update TypeScript interfaces
331+ 3 . ** Add validation functions** for user inputs
332+ 4 . ** Add unit conversion support** for metric/imperial display
333+ 5 . ** Create UI component** following existing PrimeVue patterns
334+ 6 . ** Add to main App.vue** with proper event handling
335+
336+ ### Critical File Locations
337+
338+ ** Frontend:**
339+ - ` elle-frontend/src/App.vue ` - Main application container
340+ - ` elle-frontend/src/composables/useSettings.ts ` - Settings management
341+ - ` elle-frontend/src/composables/useHAL.ts ` - HAL communication
342+ - ` elle-frontend/src/components/ ` - Vue components
343+
344+ ** Electron:**
345+ - ` elle-electron/main.ts ` - Main process, IPC handlers
346+ - ` elle-electron/electron-store/configuration.ts ` - Settings schema
347+ - ` elle-electron/preload.d.ts ` - TypeScript definitions
348+
349+ ** Backend:**
350+ - ` elle-hal/lathe_halcomp.py ` - Python Flask HAL interface
351+ - ` elle-hal/elle-lathe.ini ` - LinuxCNC configuration
352+
353+ ### Debugging Tips
354+
355+ ** Settings Issues:**
356+ - Check ` ~/.config/elle-app/appConfig.json ` for saved data
357+ - Console errors about "object could not be cloned" = serialization issue
358+ - Look for Vue refs passed without ` .value `
359+
360+ ** HAL Communication Issues:**
361+ - Check Python backend is running on port 8000
362+ - Verify HAL pins are created: ` halcmd show pin `
363+ - Check for 400 errors in network tab = invalid HAL requests
364+
365+ ** Position Calculation Issues:**
366+ - Tool offsets applied in ` useHAL.ts ` ` startPoll ` function
367+ - Axis offsets managed separately from tool offsets
368+ - Diameter mode doubles X display only, not actual position
0 commit comments