dyadmisha

dyadmisha синхронизированные коммиты с update-platform-espressif32-to-6.11.0 на dyadmisha/AI-on-the-edge-device из зеркала

17 часов назад

dyadmisha синхронизированные новые ссылки update-platform-espressif32-to-6.11.0 к dyadmisha/AI-on-the-edge-device из зеркала

17 часов назад

dyadmisha синхронизированные и удаленные ссылки develop на dyadmisha/AI-on-the-edge-device из зеркала

17 часов назад

dyadmisha синхронизированные коммиты с v4.0.0 на dyadmisha/dune-weaver из зеркала

17 часов назад

dyadmisha синхронизированные новые ссылки v4.0.0 к dyadmisha/dune-weaver из зеркала

17 часов назад

dyadmisha синхронизированные коммиты с main на dyadmisha/dune-weaver из зеркала

  • 510f20009a Fix thread-unsafe direct serial access bypassing connection lock Replace all state.conn.ser direct access with the properly locked SerialConnection abstraction methods (send, reset_input_buffer). The unlocked writes caused race conditions that corrupted Bluetooth serial connections, leading to unrecoverable I/O errors (errno 5). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 5a8083d14a feat: Complete React UI rewrite with new frontend architecture (#112) * Add homing blocking - prevent movement during homing Backend changes: - Add is_homing flag to AppState - Set flag during homing operation with proper cleanup on success/failure - Add check_homing_in_progress() helper function - Block these endpoints while homing: run_theta_rho, run_theta_rho_file, run_playlist, move_to_center, move_to_perimeter, send_coordinate - Add is_homing to status response for frontend awareness - Return HTTP 409 Conflict if action attempted during homing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix led * Add root package.json and package-lock.json - Update .gitignore to only ignore state.json instead of all *.json - Add package.json with npm scripts for development - Add package-lock.json for reproducible installs npm scripts available: - npm run dev: Start frontend and backend concurrently - npm run build: Build React frontend - npm run start: Build and start server Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Ignore additional JSON config files - playlists.json (runtime data) - metadata_cache.json (generated cache) - tsconfig.json (TypeScript config - use frontend's) - dune-weaver-touch/*.json (touch app configs) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Enable network access for Vite dev server Add --host flag to dev and preview scripts so the frontend is accessible from other machines on the network (useful for remote development on Pi) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Allow all hosts for Vite dev server Enables access via hostnames like dwg.local on local network Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Mount metadata_cache.json for persistence Without this mount, the metadata cache was regenerated on every container restart because the file was lost inside the container. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert to mounting entire app directory Mounting individual files caused issues with metadata_cache.json not being created properly. The .:/app mount is simpler and ensures all runtime files (state.json, metadata_cache.json, playlists/, etc.) are persisted automatically. Also fixed dbus socket path typo. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add settings enhancements and Docker update functionality - Add preferred port selection with auto-connect disable option - Display gear ratio and X/Y steps per mm in machine settings - Add MQTT test connection button to Home Assistant section - Change "WLED" to "LED" in Still Sands section - Implement Docker-based software update for two-container setup - Update button now always enabled for testing - Fix sensor offset input to allow clearing value - Add searchable select component Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve settings, homing auto-detection, and update flow Settings & UI: - Move timezone from Still Sands to Machine Settings (system-wide) - Add UTC offset timezones (UTC-12 to UTC+12) to selector - Remove update button, show CLI instructions instead - Remove "Paused" badge from Now Playing bar - Logs now display timestamps in configured timezone Homing: - Auto-detect sensor homing from FluidNC $22 setting - Add homing_user_override flag to respect explicit user preference - Only auto-set sensor mode if user hasn't configured otherwise Update system: - Add git pull to update_manager for local file updates - Remove non-existent frontend image pull - Handle container self-restart gracefully - Direct users to use 'dw update' from host for full updates Bug fixes: - Validate auto-play playlist exists before running - Clear invalid playlist references from state automatically Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Consolidate cache-all-previews logic and fix Docker restart - Extract shared cacheAllPreviews() function to previewCache.ts - Simplify BrowsePage and Layout modal to use shared function - Fix PlaylistsPage to validate previews before caching - Fix Docker restart using correct container name (dune-weaver-backend) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add timeout protection to cache generation Prevents backend from hanging when parsing problematic pattern files. Files that take longer than 30 seconds to parse are skipped with an error log. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix log handler performance and restore Still Sands timezone - Remove expensive timezone conversion from log handler that created ZoneInfo objects on every log message (major Pi performance issue) - Logs now use simple local system time - Move timezone setting back to Still Sands where it's actually needed - Remove unused timezone from Machine Settings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Switch Docker images to feature-react-ui branch TODO: Revert to main before merging to main branch. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix preview batch requests overwhelming backend on Pi Both BrowsePage and PlaylistsPage were sending all uncached pattern previews in a single request, causing: - 100+ second processing times for 879 files - 504 gateway timeouts on other API calls - 8.9MB responses causing nginx buffering warnings Now batches requests into groups of 10 with 100ms delays between batches, matching the cacheAllPreviews behavior. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve Now Playing bar UX and timezone input Now Playing bar: - Fix race condition where auto-collapse undid expansion on playlist start - Listen to playback-started event for more reliable expansion - Add 500ms delay before auto-collapse to prevent race conditions - Click preview image in mini view to expand - Click canvas in expanded view to collapse back Settings (Still Sands timezone): - Replace Select with Input + datalist for custom timezone support - Add UTC offset options (UTC-12 to UTC+12) - Users can now type any IANA timezone (e.g., Asia/Kolkata) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve Settings page UX and fix Auto Play issues Auto Play on Boot: - Fix playlist fetch (backend returns array directly, not object) - Add pause time unit selector (sec/min/hr) matching Playlists page - Smart conversion: 300s displays as "5 min", saves back as seconds Still Sands timezone: - Replace Select with Input + datalist for custom timezone support - Add UTC offset options (UTC-12 to UTC+12) - Users can type any IANA timezone UI polish: - Increase spacing between labels and inputs (space-y-2 → space-y-3) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add serial debug terminal, background homing, and UI improvements - Fix Python 3.9 compatibility for type hints in scheduling.py and process_pool.py - Change startup order: backend starts immediately, homing runs in background - Add homing progress overlay with streaming logs, 5s countdown after completion - Prevent movement commands (home, center, perimeter, align) while pattern running - Add serial debug terminal tab for raw command communication without full connection - Make logs drawer resizable with drag handle Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add multi-table control support with mDNS discovery Backend: - Add CORS middleware to enable cross-origin requests from other frontends - Add table identity endpoints (GET/PATCH /api/table-info) with UUID and name - Add mDNS advertisement using zeroconf (_duneweaver._tcp.local.) - Add discovery endpoint (GET /api/discover-tables) to find tables on LAN Frontend: - Add centralized API client (apiClient.ts) with configurable base URL - Add TableContext for multi-table state management with localStorage persistence - Add TableSelector component in header for switching between tables - Update WebSocket connections to use apiClient for dynamic URL targeting - Refactor key fetch calls to use apiClient Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Move serial terminal from logs drawer to Table Control page - Relocate serial terminal UI and logic from Layout to TableControlPage for better contextual placement with other table controls - Add auto-connect feature that detects main connection port - Update LED pixel order default from GRB to RGB (WS2815/WS2811) - Use apiClient for consistent WebSocket URL construction Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix nginx upstream resolution for host network mode Use 127.0.0.1:8080 instead of backend:8080 since frontend runs with network_mode: host, which disables Docker DNS resolution. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix version_manager method call in get_table_info endpoint Use await get_current_version() instead of non-existent get_version(). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix remaining get_version() calls to use get_current_version() - modules/core/mdns.py: Fix mDNS advertisement (2 occurrences) - main.py: Fix discover_tables endpoint Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix DW LEDs race condition and mDNS async warning - Fix DW LEDs not working after background homing: connect_device() was overwriting led_controller with None because it didn't handle "dw_leds" provider. Now preserves existing controller or initializes if needed. - Use AsyncZeroconf in discover_tables() to fix blocking I/O warning - Add frontend dist volume mount for dev without rebuild Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix DW LEDs not initializing on application restart The DW LED controller uses lazy hardware initialization, but startup code only created the LEDInterface without triggering initialization. Now calls check_status() and effect_idle() on startup, matching /set_led_config behavior. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix DW LEDs staying on green blink after connection The effect_idle() function was doing nothing when no idle effect was configured, causing the green "connected" blink to persist. Now defaults to Rainbow effect using controller's current speed/intensity parameters. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Use controller's current parameters for default Rainbow idle effect Explicitly pass speed, intensity, and colors from controller state instead of relying on implicit values. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Remove static/dist volume mount causing nginx 403 on Pi The mount overrides the built-in frontend with local directory that may not exist on Pi, causing 403 Forbidden errors. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Remove mDNS implementation and zeroconf dependency - Remove zeroconf from requirements.txt - Remove mdns module import and startup/shutdown code - Remove /api/discover-tables endpoint - Delete modules/core/mdns.py Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix remote table control and improve multi-table stability - Convert 56+ direct fetch() calls to apiClient across all pages - BrowsePage, LEDPage, SettingsPage, PlaylistsPage, TableControlPage - previewCache, Layout, NowPlayingBar - Add apiClient.delete() body support for DELETE requests with payload - Fix table selection persistence across page refreshes - Use ref to track restored selection before async state updates - Reload page on table switch for clean WebSocket/cache state - Fix WebSocket reconnection bugs in Layout and NowPlayingBar - Add shouldReconnect flag to prevent stale onclose handlers - Clear pending reconnect timeouts properly - Optimize NowPlayingBar preview fetching - Skip fetch when bar is hidden - Track last fetched files to prevent duplicate requests - Fix DW LED default Rainbow speed to 60 for smoother animation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve mobile UI layout and fix pattern stop hanging Mobile UI improvements: - Add hamburger menu for header actions on mobile - Make navbar fixed with safe area insets for iOS - Use dynamic viewport height (dvh) for proper mobile sizing - Compact page headers (text-xl on mobile, text-3xl on desktop) - Improve Playlists page controls layout with stacking - Make table selector and playlist actions visible on mobile (no hover) - Compact Browse page filters (search + category on same row) - Reduce Serial Terminal header overflow on mobile Pattern execution fix: - Add stop request checks in motion thread to prevent hanging - Add 10s timeout on pattern lock acquisition in stop_actions - Add 30s overall timeout in motion command retry loop - Clear motion queue when stop is requested Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix Safari mobile WebSocket issues and improve request handling - Fix WebSocket race condition causing "closed before established" error on Safari mobile by assigning wsRef immediately after creation - Bypass Vite WebSocket proxy in dev mode for Safari mobile compatibility (connect directly to port 8080 instead of proxying through 5173) - Add AbortController to cancel in-flight preview requests on page navigation (BrowsePage, PlaylistsPage) - Fix cache manager race condition with asyncio.Lock for metadata writes - Add debouncing (300ms) to LED color picker to reduce API spam - Remove 30s motion thread timeout while preserving force stop capability - Add Reset button (Ctrl+X) to serial terminal section - Remove table discovery refresh button from TableSelector - Fix TableContext reload loop on initial table selection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix TypeScript build error for NodeJS.Timeout type Use ReturnType<typeof setTimeout> instead of NodeJS.Timeout for browser compatibility in Docker build environment. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix CPU spike on pattern start by moving blocking I/O to thread - Wrap parse_theta_rho_file() with asyncio.to_thread() in run_theta_rho_file() - Wrap load_metadata_cache() with asyncio.to_thread() in run_theta_rho_files() This prevents the event loop from blocking during file parsing, keeping WebSocket updates, LED control, and status broadcasts responsive while large pattern files are being read. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Remove timeout from motion thread 'ok' response waiting The motion thread now waits indefinitely for hardware 'ok' response, only aborting on stop_requested. Use force stop if hardware becomes unresponsive. Exception-based retries still in place for connection errors. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert motion thread changes from 1b02b8c that caused pattern hangs Reverts _execute_move() and _send_grbl_coordinates_sync() to their pre-commit state. The stop_requested checks added in that commit were interfering with normal pattern playback. The motion thread now uses the simpler, working logic: - _execute_move: Only checks self.running, not stop_requested - _send_grbl_coordinates_sync: Simple retry loop without stop checks Stop functionality still works via stop_actions() setting state flags that are checked in the main pattern execution loop. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * add stop check * Clear pause time between patterns on stop Always clear pause_time_remaining and original_pause_time when stopping, not just when clearing the playlist. This ensures the UI doesn't show stale countdown values after stopping. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add historical ETA, persist pre-execution selection, fix mobile UI - Display historical execution time as ETA when pattern was previously completed at the same speed (shows history icon indicator) - Persist pre-execution action selection to localStorage (shared between Browse and Playlists pages) - Fix delete pattern 404 by adding endpoint to Vite proxy config - Fix mobile UI: circular preview containers, progress bar spacing - Remove marquee effect from pattern name display Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix dark mode color hierarchy for better visual distinction - Increase border color from 25% to 32% lightness for visibility - Increase muted/secondary/accent from 20% to 25% lightness - Increase input background from 22% to 28% lightness - Remove nested bg-card from inner containers (use border only) - Use bg-muted/50 for info cards and stat displays - Fix Alert component using bg-background (too dark inside cards) - Fix Still Sands time period cards background - Fix LED page effect preview boxes background Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix process pool semaphore leaks and WebSocket connection warnings Backend: - Add shutdown flag to prevent race conditions in process pool - Use wait=True in signal handler to allow workers to release semaphores Frontend: - Fix WebSocket cleanup to avoid closing CONNECTING sockets - Add onopen handlers to gracefully close orphaned connections - Properly handle React StrictMode double-mounting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix "Up Next" showing wrong pattern during clear pattern execution When a clear pattern was running for pattern 1, "Up Next" incorrectly showed pattern 2 instead of pattern 1. The issue had two parts: 1. is_clearing flag was immediately reset to False by stop_actions() called inside _execute_pattern_internal(), before the pattern started 2. get_status() calculated next_file as playlist[current_index + 1] regardless of whether a clear pattern was running Fixed by: - Preserving is_clearing flag around stop_actions() call - Setting is_clearing = True before clear pattern, False after - Modifying get_status() to return current main pattern as next_file when is_clearing is True - Adding is_clearing to status response for frontend awareness Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve NowPlayingBar UI: spacing, mobile queue access, drag-and-drop - Fix remaining time too close to progress bar by increasing width from w-16 to w-20 when showing historical ETA and gap to 1.5 - Add queue button to header on mobile for easy queue access - Refactor queue dialog to use drag-and-drop reordering with dnd-kit - Replace up/down arrow buttons with drag handles for more intuitive UX - Remove "hide clear patterns" toggle (no longer needed since playlists now only contain main patterns) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * simplify playlist playback * Reduce default process pool workers for low-RAM devices Default to 1 worker instead of (cpu_count - 1) to conserve RAM on memory-constrained devices like Pi Zero 2 W (512MB). This prevents memory pressure that causes UI sluggishness and unresponsive stops. Added POOL_WORKERS env var to override if more workers are needed on systems with more RAM. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix stale "Waiting for next pattern" UI after skipping pause Clear pause_time_remaining and original_pause_time when a new pattern starts executing, not just after the pause loop ends. This prevents stale waiting state from showing in the UI if skip was triggered during a pause period. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix stop not interrupting motion thread retry loop The motion thread's retry loop was checking stop_requested only before sending commands, not at the start of each iteration or while waiting for responses. This caused infinite "No 'ok' received" retries when stop was requested. Added stop checks at: - Start of each retry iteration (immediate return) - Inside response wait loop (escape blocking readline) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Bump version to 4.0.0 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Auto-create playlist if not found on get_playlist Instead of returning 404 when a playlist doesn't exist, automatically create an empty playlist. This handles cases like "Favorites" where the UI expects the playlist to exist. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix status indicator not syncing when switching tables Reset isConnected and isBackendConnected to false when switching tables so the header status indicator shows the transitional state until the new table's WebSocket connection reports its actual status. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve UI responsiveness, auto-connect options, and LED stability Frontend: - Fix Select dropdowns overflowing viewport (add max-height + scroll) - Make Custom Logo upload button stack on mobile - Add all LED color order options (BGR, RBG, GBR, BRG) with grouping - Fix LED page icon alignment and mobile speed/intensity layout - Redesign mobile filter bar (compact single row) - Rename "Uncategorized" to "Default Patterns" Backend: - Add auto-connect disabled mode (__none__ option) - Deprioritize /dev/ttyS0 during auto-connect (still available manually) - Fix LED hardware change detection using wrong defaults - Add 500ms delay between LED controller stop/reinit for stability - Change default pixel order to RGB (WS2815) and GPIO to 18 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Auto-save auto-connect setting on dropdown change - Remove need to click Save button after selecting auto-connect option - Setting now saves immediately when dropdown value changes - Shows toast confirmation with selected option Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix auto-connect settings and SelectLabel error - Use explicit string values for preferred_port (__auto__, __none__) - Backend stores values directly instead of converting to null - Fix SelectLabel must be within SelectGroup error - Connection manager handles both __auto__ and null for backwards compat Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Redesign playlist controls and improve button styling - Convert playlist controls to floating pill-shaped element with blur backdrop - Change all outline buttons to secondary variant across app - Enhance secondary button hover with scale, shadow, and accent color - Highlight clear pattern icon when a pattern is selected - Add swap icon to pause time to indicate unit is clickable Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add pattern history display, queue management, and multi-table UX improvements - Add pattern execution history showing last run time and speed in browse panel - Add "Play Next" and "Add to Queue" buttons to insert patterns into running playlist - Replace custom slide-in panel with shadcn Sheet component for better UX - Show table name in header when multiple tables are connected - Fix CORS configuration for cross-origin multi-table access - Cache parsed coordinates in state to avoid re-parsing large files on Pi Zero 2W - Use thread executor instead of process pool for coordinate parsing (reduces memory pressure) - Add Now Playing button to desktop header for quick access Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve mobile responsiveness and unify page styling - Match navbar background with header (bg-card) - Reduce page title font size and add left padding - Make filter bar compact on mobile with icon-only buttons - Standardize page spacing across all pages (py-3 sm:py-6) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add play time badges, editable numeric inputs, and UI refinements - Add play time badges on pattern cards showing last execution duration - Make Speed, Intensity, Number of LEDs, and Pause inputs editable via typing - Replace timezone datalist with SearchableSelect for better UX - Add soft reset button to Control page (sends GRBL Ctrl+X) - Change Home button to primary (blue) and Reset to secondary styling - Reduce Select dropdown max-height from 384px to 256px - Add /soft_reset and /api/pattern_history_all backend endpoints Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix playlist page layout and silence auto-connect toast - Fix playlist container height to account for bottom navbar - Align sidebar and main content headers with matching structure - Add playlist count subtitle to sidebar header - Make serial terminal auto-connect silent (no toast on page load) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * update * Fix TypeScript error in serial connect button onClick handler Wrap handleSerialConnect in arrow function to prevent MouseEvent being passed as the silent parameter, which caused a type mismatch during build. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix stuck pattern state and improve stop/reset reliability - Add timeout (30s) to check_idle_async() to prevent infinite loops - check_idle_async() now respects stop_requested flag for early exit - Add /force_stop endpoint for nuclear cleanup when normal stop fails - /stop_execution now returns error on timeout, triggering force_stop fallback - /soft_reset uses direct serial write for more reliable reset - Reset button calls force_stop first to clear stuck state - Stop buttons in UI auto-retry with force_stop on failure Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert backend changes to debug serial terminal issue Temporarily reverting stop/reset reliability changes to test if they caused the serial terminal to stop receiving responses. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Prevent crash when sensor homing partially fails Skip position zeroing (x0 y0) if not both X and Y axes received homing confirmation. Moving to zero with an unknown axis position would crash the machine - essentially performing unintended crash homing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add force stop endpoint and improve pattern execution control - Add /force_stop endpoint to clear all pattern state when normal stop times out - Improve soft_reset to send Ctrl+X directly via serial for reliability - Add timeout parameter to check_idle_async with stop request handling - Fix homing to skip zeroing only when X homed but Y failed (avoids Y crash) - Return success/failure from stop_actions for better error handling - Change default LED speed from 128 to 50 - Remove "(common)" labels from LED pixel order options Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix WebSocket race condition on page load for multi-table support Initialize apiClient baseUrl synchronously from localStorage before any React components mount. This prevents WebSockets from briefly connecting to the wrong backend when a remote table was previously selected. Also skip notifying listeners when setBaseUrl is called with the same URL to avoid unnecessary WebSocket reconnections. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Move auto-homing to after pause time in playlist execution Relocate the auto-homing check from immediately after pattern completion to after the pause time, right before the next clear pattern starts. This allows users to enjoy the completed pattern during the full pause duration before homing disrupts it. The homing now logically precedes the clear pattern which erases the sand anyway. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix patterns not loading due to stale localStorage URL initialization CRITICAL FIX: Reverted apiClient localStorage pre-initialization that could cause all API calls to silently fail if users had stale table data pointing to unreachable servers. Also includes: - Increase main content top padding (pt-16 → pt-[4.5rem]) to prevent header overlap on mobile - Make Add Pattern and Cache buttons responsive (h-9 on mobile) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix nested button HTML error in PatternCard Change favorite toggle from <button> to <span role="button"> to avoid invalid nested button elements. Adds proper keyboard accessibility with tabIndex and onKeyDown handlers for Enter/Space keys. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix race condition with stale serial port from wrong backend When using multi-table mode, the frontend could receive serial port data from a different backend during the brief window before TableContext validates the active table URL. This caused connect attempts with non-existent ports (e.g., Mac's /dev/cu.usbserial on a Pi). Fix: Validate that the port returned from /serial_status exists in the available ports list from /list_serial_ports before setting it. If the port doesn't exist on this machine, log a warning and ignore it. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix move_to_center/perimeter not working after pattern stop When a pattern was stopped, state.stop_requested remained True. The motion control thread checks this flag and aborts commands immediately, causing manual move commands (center/perimeter) to return 200 OK but never actually send G-code to the controller. Fix: Clear stop_requested at the start of move_polar() so manual movement commands always execute regardless of previous stop state. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix SelectItem highlight not matching pill-shaped dropdown Changed SelectItem border-radius from rounded-sm to rounded-xl to match the pill-shaped aesthetic of SelectTrigger (rounded-full) and SelectContent (rounded-2xl). The highlight now properly fills the item. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add event-driven stop/skip for instant interrupt response Previously, stop and skip requests during scheduled pauses were ignored or delayed up to 1 second due to polling-based checks. This caused the UI to appear frozen when users tried to skip or stop during Still Sands periods. Changes: - Add asyncio.Event backing to stop_requested/skip_requested flags - Add wait_for_interrupt() method for instant event-driven waiting - Fix in-pattern pause loop to respond to stop/skip immediately - Fix post-pattern scheduled pause to respond to skip (not just stop) - Increase DEFAULT_WORKERS from 1 to 3 for better parallelism - Remove deprecated .cursorrules file (replaced by .claude/CLAUDE.md) The property setters automatically sync flags and events, so existing code using state.stop_requested = True works unchanged while async code now gets instant wake-up via events. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix stop timeout during pause and stale "waiting" UI state Two issues fixed: 1. Stop/skip during manual pause could hang indefinitely: - The event wait had no timeout, relying solely on asyncio.Event - If stop was called from sync context (no event loop), events weren't set - Added 1-second timeout to ensure flags are polled as fallback 2. "Waiting for next pattern" shown during pattern playback: - Single pattern execution didn't clear pause_time_remaining - Stale values from previous playlist caused incorrect UI state - Now cleared at start of run_theta_rho_file() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve UI consistency and responsiveness - Browse page: Add gap between icons and text in filter dropdowns - NowPlayingBar: Make real-time preview responsive (42vh on desktop, capped at 500px), increase vertical padding - PlaylistsPage: Restyle pattern picker modal filters to match Browse page (pill-shaped buttons, icon-only on mobile, consistent order: folder → sort → direction) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add host-based update watcher for Docker deployments Implements a signal-based update mechanism that allows triggering `dw update` from within Docker containers. The container creates a trigger file that a host systemd service watches for, then executes the full update process on the host machine. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add Update Now button to Settings page Adds a button to trigger software updates from the web UI instead of requiring SSH access to run `dw update` manually. Shows status feedback during update process. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve Now Playing Bar positioning and add favorite to pattern panel - Fix Now Playing Bar position calculation when logs drawer is open - Pass dynamic logsDrawerHeight instead of hardcoded value - Add vertical padding to collapsed bar content - Adjust bar heights for better spacing - Add favorite toggle button in pattern details panel header - Add env vars for testing update functionality Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix docker-compose.yml invalid empty environment mapping Move environment block to comments since all values were commented out. An empty environment: key with only comments is invalid YAML. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix Python 3.9 compatibility for type hints Use typing.Optional and typing.Tuple instead of Python 3.10+ union syntax (str | None) for backwards compatibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert auto-update feature, instruct users to SSH and run dw update The host-based update watcher added complexity and required manual service installation. Simpler to just tell users to SSH in and run the dw update command directly. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix dw update to re-exec with new CLI after git pull The script now re-executes itself after updating the dw CLI file, ensuring any new update logic in the script actually runs. Uses --continue flag to skip the pull phase on re-exec. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add sort by favorites option to Browse and Playlist pages - Add 'favorites' to SortOption type in lib/types.ts - BrowsePage: Add favorites sorting (favorites first, then by name) - PlaylistsPage: Add favorites state, load from Favorites playlist - PlaylistsPage: Add favorites sorting to pattern picker modal - Both pages now show Favorites as first sort option in dropdown Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Change header Reset button to do table soft reset instead of Docker restart The Reset button (restart_alt icon) in the header now: - Calls /force_stop to clear any stuck state - Calls /soft_reset to reset the DLC32/ESP32 - Shows "Reset sent. Homing required." toast This matches the behavior of the Reset button in TableControlPage. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add missing endpoints to nginx proxy config Added force_stop, soft_reset, reorder_playlist, and delete_theta_rho_file to the nginx proxy regex. These were missing, causing 404s when accessing a remote table through nginx. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert header button to Docker restart, remove TableControl Reset button - Layout.tsx: Revert handleRestart to restart Docker containers (with confirmation) - Layout.tsx: Change labels back to "Restart Docker" - TableControlPage.tsx: Remove Reset button (keep only Home and Stop) - TableControlPage.tsx: Remove handleSoftReset function - TableControlPage.tsx: Remove client-side check blocking Home button Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix clipboard copy for non-HTTPS contexts (http://dwg.local) Add copyToClipboard helper that falls back to document.execCommand('copy') when navigator.clipboard is unavailable (non-secure HTTP contexts). Fixes copy button in Homing Log and main logs drawer. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve UI consistency and mobile experience - NowPlayingBar: Add pattern preview in expanded view, optimistic drag-drop - NowPlayingBar: Show move to top/bottom buttons always on mobile - Layout: Unify desktop/mobile header with same 3-icon layout (play, table, menu) - Layout: Tighter icon spacing, fix active table name display - TableSelector: Remove dropdown arrow, move checkmark to far right - BrowsePage: Add swipe to dismiss for pattern detail sheet Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * minor ui change * Add PWA support and improve mobile experience - Add vite-plugin-pwa for service worker and caching - Add iOS safe area support (Dynamic Island, notch) - Add mobile drill-down navigation for Playlists with swipe-back gesture - Update favicon/PWA icons to square format (OS applies masks) - Add circular favicons with transparent background for browser tabs - Add dynamic manifest endpoint for custom branding support - Generate proper PWA icons on custom logo upload - Allow dismissing homing splash screen - Add scroll-to-top on page navigation - Enable header blur only on Browse page Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve UI with floating Now Playing button and various fixes - Add centered floating Now Playing button above nav bar (all screens) - Remove Now Playing button from header to declutter - Fix table selector dropdown alignment with header pill - Show cache progress percentage on mobile - Fix toast notifications blocked by Dynamic Island in PWA mode - Improve lazy loading for pattern previews in playlists and queue Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Show table icons in table selector dropdown - Add customLogo field to Table interface - Fetch settings when discovering/adding tables to get custom logo - Refresh remote tables in background to fetch their logos - Replace wifi icons with table's actual icon/logo - Add status dot overlay to indicate online/offline state Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve Now Playing bar mobile UX and PWA safe areas - Lock body scroll when Now Playing bar is visible - Add swipe-to-dismiss for queue dialog with visual indicator - Allow scrolling inside queue while preventing background scroll - Add safe area padding for Dynamic Island in expanded view - Position header buttons below Dynamic Island when expanded Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Persist added tables in backend for multi-device access Backend: - Add known_tables field to AppState for persistent storage - Add GET/POST/DELETE/PATCH /api/known-tables endpoints - Tables stored in state.json alongside other settings Frontend: - Fetch known tables from backend on discovery - Persist added tables to backend via POST - Remove tables from backend via DELETE - Update known table names in backend for remote tables - Keep localStorage for active table selection (client-specific) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix multi-table WebSocket connections failing in production The issue was that table switching worked in development but failed in production (port 80). Two problems were fixed: 1. Removed reliance on stale `isCurrent` flag from localStorage which could incorrectly prevent the base URL from being set 2. Added URL normalization for comparison to handle port differences (e.g., http://host:80 vs http://host are now correctly recognized as the same origin) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add debug logging for multi-table WebSocket issue Adds console.log statements to track: - When setBaseUrl is called and with what values - What WebSocket URLs are generated - Table restoration from localStorage and URL comparison Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix race condition: pre-initialize apiClient base URL from localStorage WebSocket connections were being established before TableContext had a chance to set the base URL, causing connections to go to the wrong server when switching tables. Solution: Initialize the base URL synchronously at module load time, before React renders. This ensures the correct URL is available immediately when components mount and create WebSocket connections. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Remove debug logging from multi-table fix Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Center real-time preview canvas in expanded view Added flex-1 to the canvas container so it expands to fill available space, allowing the canvas to be properly centered. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Center real-time preview canvas in expanded Now Playing view - Added h-full to max-width container for proper height inheritance - Added flex-1 to canvas wrapper to fill available space - Removed conflicting md:justify-center from inner container Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Prevent debug terminal from interfering with pattern execution - Remove auto-connect to serial debug terminal on page load - Add warning alert advising users not to use terminal during pattern execution - Fixes silent pattern failure when debug terminal intercepts GRBL responses Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix build error and add retry logic for motion commands - Remove unused mainConnectionPort state (fixes TS6133 build error) - Add 1-second timeout with automatic resend for motion commands - Motion thread now retries forever until 'ok' is received - Prevents silent hang if response is missed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Center warning text vertically in alert box Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add Reset button with confirmation dialog - Sends Ctrl+X soft reset to controller - Shows warning that homing is required after reset - Uses existing /soft_reset API endpoint Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Increase serial port selector width to prevent text cutoff Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Replace native select with shadcn Select for serial port - Fixes dropdown positioning issues with native select - Uses Radix UI portal for proper z-index and positioning - Auto-refreshes port list when dropdown opens Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert retry timeout - wait indefinitely for GRBL 'ok' GRBL only sends 'ok' after a move completes, which can take many seconds at slow speeds. The 1-second timeout was causing premature resends and duplicate commands. Reverted to original behavior: wait indefinitely for 'ok' response. Added stop_requested checks so patterns can still be cancelled. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Restore null check in get_status_response() Prevents crash when called without active connection. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix serial stability issues caused by asyncio event overhead - Make stop_requested/skip_requested setters thread-safe using call_soon_threadsafe() for cross-thread event manipulation - Remove state.stop_requested=False from move_polar() which was triggering event manipulation thousands of times per pattern - Add stop_requested clearing to manual move endpoints instead (/move_to_center, /move_to_perimeter, /send_coordinate) - Fix BrowsePage upload refresh to call fetchPatterns() The root cause was move_polar() setting stop_requested on every coordinate, causing constant asyncio event manipulation that created race conditions and overhead during pattern execution. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Update package-lock.json dependencies Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix CPU spin loop in motion thread readline wait Added sleep(0.01) after readline() to prevent 100% CPU usage when readline() returns empty (timeout or bad serial state). Without this, the inner while loop would spin continuously. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Remove dangerous lock=None in connection close methods Setting self.lock = None after close() caused race conditions: - Motion thread calls readline() with "with self.lock:" - If close() was called, lock is None - AttributeError is caught, motion thread retries forever - Pattern hangs waiting for "ok" that never comes This was a regression not present in main branch. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix UI showing stale countdown after skip during pause Clear both pause_time_remaining and original_pause_time immediately when skip breaks the pause loop. Previously original_pause_time wasn't cleared until the next pattern started, causing the UI to show stale countdown state. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add 120s timeout to motion thread readline loop Previously the motion thread would wait indefinitely for 'ok' response. If serial communication fails silently (no exception, just no data), the pattern would hang forever. Now after 120 seconds without 'ok', the motion thread: - Logs an error about the timeout - Sets stop_requested = True to stop the pattern - Returns False to signal the failure Also added logging for GRBL error/alarm responses for debugging. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix race condition with multiple playlist tasks running Previously, stopping a playlist only set flags but didn't cancel the actual asyncio task. When starting a new playlist immediately after: 1. Old task continues running (just between patterns) 2. New playlist clears stop_requested 3. Old task sees stop_requested=False and continues! Now: - Track the playlist task in _current_playlist_task - cancel_current_playlist() properly cancels and awaits the task - stop_actions() calls cancel_current_playlist() when clearing playlist - run_playlist() cancels any existing task before starting new one This prevents "ghost" playlists from running in parallel. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add validation for coordinate calculations to prevent GRBL error:2 GRBL error:2 means "bad number format" - happens when coordinates contain inf, nan, or other invalid values. Added: - Protection against division by zero in offset calculation - Validation that coordinates are finite before sending to GRBL - Detailed error logging when invalid values detected - Stops pattern gracefully instead of hanging on repeated errors Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Stop pattern on GRBL error/alarm instead of hanging When GRBL returns an error (like error:2) or alarm, it will NOT send 'ok' afterwards. Previously the code just logged a warning and kept waiting for 'ok' until timeout (120s). Now GRBL errors/alarms immediately: - Log the error with the failed command - Set stop_requested = True - Return False to stop pattern execution This provides immediate feedback instead of hanging for 2 minutes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add NaN/Infinity validation before sending GRBL coordinates GRBL error:2 ("Numeric value format is not valid") can be caused by NaN or Infinity values in coordinates. This can happen if: - y_steps_per_mm = 0 (division by zero in offset calculation) - gear_ratio = 0 (division by zero in offset calculation) Now validates coordinates before sending and logs detailed diagnostic info if invalid values are detected, helping identify the root cause. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix homing timeout due to WPos vs MPos format mismatch - Support both WPos and MPos GRBL status formats (depends on $10 setting) - Add guard against None machine position when homing fails - Prevents NoneType + float crash in pattern execution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix get_machine_position to also accept WPos format Missed this function in the previous fix - it was still checking only for MPos, causing position query timeouts after homing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add debug logging for GRBL response timeout investigation - Remove time.sleep(0.01) to match main branch behavior - Log unexpected GRBL responses (neither ok/error/alarm) - Log waiting status every 30s during long waits This helps diagnose why Pi 3B+ times out on feature branch but not main. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * TEMP: Disable real-time scheduling to test Pi 3B+ serial timeout Hypothesis: SCHED_RR priority 60 + CPU 0 pinning may be blocking serial interrupt handling on Pi 3B+, causing the motion thread to never receive 'ok' responses from GRBL. CPU 0 typically handles hardware interrupts including serial ports. Running a real-time thread there might starve the interrupt handler. This is a test commit - will be reverted or made configurable based on results. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix serial echo causing GRBL communication failure on Pi 3B+ Root cause: On Pi 3B+ with /dev/ttyAMA0, the serial port had echo enabled at the TTY level. This caused: 1. Sent G-code commands echoed back as "responses" 2. Motion thread waiting for 'ok' but receiving its own commands 3. Buffer corruption merging commands (G1 G53 -> G10G53) 4. GRBL error from corrupted command, stopping pattern Fix: Disable ECHO and related flags via termios when opening the serial connection. This ensures raw serial communication without any TTY processing that could interfere. Also re-enables real-time scheduling which wasn't the cause. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Handle FluidNC command echo gracefully FluidNC firmware echoes commands back before sending 'ok'. Instead of logging warnings for each echo, silently skip echoed G-code commands (G0, G1, G2, G3, $J, M) and continue reading to get the actual 'ok' response. This reduces log spam while maintaining proper error detection for actual GRBL errors and alarms. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Disable SCHED_RR - causes serial buffer corruption on Pi 3B+ The real-time scheduling (SCHED_RR priority 60 + CPU 0 pinning) appears to cause serial buffer corruption on Pi 3B+, resulting in: - Commands being merged (e.g., "G1 G53" -> "G10G53") - GRBL errors from corrupted commands - Pattern execution failures This is separate from the FluidNC echo issue (which main branch handled silently). The corruption is timing-related and specific to certain Pi models. Keeping disabled until we can investigate proper CPU affinity settings that don't interfere with serial I/O. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert termios modifications - may cause serial corruption The termios changes (disabling ECHO, ICANON) may be causing serial data corruption (G1 -> O1). Main branch doesn't have these modifications and works fine. The FluidNC echo is handled in pattern_manager.py by ignoring echoed G-code commands, so termios-level echo suppression is not needed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add serial corruption retry logic for Pi 3B+ UART timing issues - Add reset_input_buffer() method to SerialConnection for clearing stale data - Clear serial input buffer before sending G-code commands - Add 5ms post-send delay for UART buffer stabilization - Implement retry logic (up to 3 retries) for corruption-type GRBL errors (error:1, error:2, error:20-23 indicate syntax errors from bit flips) - Throttle WebSocket status polling during pattern execution (2s vs 1s) - Detect MSG:ERR: Bad GCode messages as corruption indicators This addresses serial corruption on Pi 3B+ where G-code commands get garbled (e.g., G53 → G5s) due to UART timing issues under asyncio load. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add timeout recovery logic for lost 'ok' responses on Pi 3B+ When a 120s timeout occurs waiting for 'ok', the code now attempts recovery: - Sends status query '?' to check if machine is still responsive - If machine is Idle: assumes command completed, 'ok' was lost - continues pattern - If machine is Run: extends timeout as movement is still in progress - If delayed 'ok' received during recovery: accepts it and continues - If no response: retries the command (up to 2 times) before stopping This handles cases where the serial 'ok' response is completely lost due to UART timing issues on Pi 3B+, without unnecessarily stopping patterns. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add comprehensive logging to timeout recovery for diagnosis Enhances the timeout recovery section with detailed logging to help diagnose why recovery fails in some cases (user reported GRBL was Idle but recovery didn't detect it). New logging includes: - Failed G-code command and retry counts - Connection type and state validation - Buffer clear confirmation and bytes waiting - Each response received during recovery (at INFO level) - Summary of all responses received - Clear failure summary with possible causes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Switch from machine coordinates (G53) to work coordinates with reset This prevents MPos from accumulating indefinitely and hitting soft limits (error:30) during long pattern sequences. Changes: - Add reset_work_coordinates() to clear G92/G54 offsets on connection - Remove G53 from G1 commands to use work coordinates (G54 default) - Add G92 X0 in reset_theta() to reset work X position each pattern - Reduce coordinate precision to 2 decimals The G92 X0 command sets current position as X=0 without moving, keeping coordinates bounded. Soft limits still check MPos, so safety is preserved. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Increase serial retry limits to 10 for better Pi 3B+ reliability Raises both corruption and timeout retry limits from 3/2 to 10 to handle persistent UART timing issues on Raspberry Pi 3B+. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add Y axis reset to work coordinate reset function Now resets both X and Y work coordinates with G92 X0 Y0 to prevent coordinate accumulation on both axes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Clean up log messages - Simplify work coordinates reset log message - Remove noisy real-time scheduling disabled log Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Revert process isolation and real-time scheduling (commit 5a8643c) Remove ProcessPoolExecutor and real-time scheduling features that were causing issues on some systems: - Remove modules/core/process_pool.py - Remove modules/core/scheduling.py - Revert cache_manager.py to use asyncio.to_thread - Revert preview.py to use asyncio.to_thread - Remove CPU pinning and priority elevation from motion/LED threads Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add .vite/ to gitignore Vite's cache directory should not be committed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Use $Bye for hard reset instead of G92 X0 Y0 G92 only sets work coordinate offset without changing MPos, causing position queries to return stale values. $Bye performs a full FluidNC soft reset which properly clears position counters to 0. - Add perform_soft_reset() in connection_manager with proper wait logic - Wait for "Grbl" startup banner (5s timeout) before proceeding - Send $X unlock after reset in case of alarm state - Simplify reset_theta() to use shared soft reset function - Update /soft_reset endpoint to use new function Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add soft reset on device init and support both GRBL/FluidNC - Perform soft reset before get_machine_steps() in device_init() - Detect firmware type and use appropriate reset command: - FluidNC: $Bye - GRBL: Ctrl+X (0x18) - Refactor to sync/async versions for different contexts - Ensures controller is in known state before querying Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix $Bye reset reliability and prevent position drift - Add idle check before reset_theta() to prevent error:25 when controller is still processing commands - Add retry logic (3 attempts with 5s/7s/9s timeouts) to soft reset - Fail-fast: only set position to (0,0) when confirmation received, preventing position drift from accumulating over long operations - Add CPU affinity: pin Docker backend to cores 0-2, touch app to core 3 with Nice=10 to prevent serial I/O timing issues Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix device init: check position before reset to avoid unnecessary homing Query machine position BEFORE soft reset to determine if homing is needed. Previously, reset was done first which zeroed position, causing the comparison to always trigger homing even when machine retained position. New sequence: 1. Query machine position (before reset) 2. Compare with saved state to decide if homing needed 3. Perform soft reset for clean controller state 4. Home only if position was mismatched Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Increase soft reset retries to 5 with exponential backoff - Increase max_retries from 3 to 5 for better reliability - Timeout uses 1.5x backoff: 5s, 7.5s, 11s, 17s, 25s - Retry delay uses 2x backoff: 1s, 2s, 4s, 8s between attempts - Gives controller more time to recover from transient issues Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Increase homing timeout from 90s to 120s Provides buffer for controller to stabilize after soft reset recovery before expecting reliable communication during homing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Update frontend: remove Ctrl+X reference from soft reset UI Backend now auto-detects firmware and sends appropriate command: - FluidNC: $Bye - GRBL: Ctrl+X (0x18) UI now shows generic "Soft Reset" instead of "Ctrl+X Soft Reset" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * extend logs * chore(backend-testing-01): create test directory structure - tests/ root with __init__.py - tests/unit/ for mocked unit tests (CI) - tests/integration/ for hardware tests (local only) - tests/fixtures/ for test data files * chore(backend-testing-01): add testing dependencies - pytest + pytest-asyncio for async test support - pytest-cov for coverage reporting - pytest-timeout for test timeouts - httpx for async API testing - mock-serial for serial port mocking - factory-boy + faker for test data generation * chore(backend-testing-01): configure pytest in pyproject.toml - testpaths set to tests/ - asyncio_mode = auto for pytest-asyncio - asyncio_default_fixture_loop_scope = function - markers for hardware and slow tests - coverage settings with relative_files = true * chore(backend-testing-01): create root conftest.py with shared fixtures - pytest_configure for CI detection and markers - pytest_collection_modifyitems to auto-skip hardware tests in CI - async_client fixture for API testing with httpx - mock_state fixture with comprehensive state defaults - mock_connection fixture for serial/websocket mocking - patterns_dir fixture for temporary test patterns * test(backend-testing-01): add playlist_manager CRUD tests - test_load_playlists_empty_file, test_load_playlists_with_data - test_create_playlist, test_create_playlist_overwrites_existing - test_get_playlist_exists, test_get_playlist_not_found - test_modify_playlist, test_delete_playlist - test_list_all_playlists, test_add_to_playlist - test_rename_playlist_* (6 edge cases) 20 tests total, all passing * test(backend-testing-01): add pattern_manager parsing tests - parse_theta_rho_file tests (valid, comments, empty lines, not found) - parse_theta_rho_file edge cases (invalid lines, whitespace, scientific notation, negative) - list_theta_rho_files tests (basic, subdirectories, skip cached_images) - get_status tests (idle, running, paused, playlist) - is_clear_pattern tests (standard, mini, pro, regular patterns) 22 tests total, all passing * test(backend-testing-01): add connection_manager parsing tests - parse_machine_position tests (MPos, WPos formats) - parse_machine_position edge cases (invalid, run/alarm state, negative, high precision) - list_serial_ports tests (filter ignored, empty, all ignored) - BaseConnection interface tests - IGNORE_PORTS and DEPRIORITIZED_PORTS constant tests - is_machine_idle tests (no connection, idle, running) 21 tests total, all passing * chore(backend-testing-01): create unit conftest with mocked dependencies - mock_state_unit fixture with comprehensive state defaults - mock_connection_unit fixture for hardware mocking - app_with_mocked_state fixture for patched app testing - async_client_with_mocked_state fixture for API testing - cleanup_app_overrides fixture for dependency cleanup * test(backend-testing-01): add status and info API endpoint tests - /serial_status tests (connected, disconnected states) - /list_serial_ports tests (returns list, empty) - /api/settings tests (structure, effective_table_type) - /api/table-info tests (configured, not configured) 9 tests total, all passing * test(backend-testing-01): add pattern API endpoint tests - /list_theta_rho_files tests (list, empty) - /list_theta_rho_files_with_metadata tests (structure) - /get_theta_rho_coordinates tests (valid file, not found) - /run_theta_rho tests (disconnected, during homing, not found) - /stop_execution tests (success, disconnected) - /pause_execution and /resume_execution tests - /delete_theta_rho_file tests (success, not found) 14 tests total, all passing * test(backend-testing-01): add playlist API endpoint tests - /list_all_playlists tests (list, empty) - /get_playlist tests (exists, auto-creates if not found) - /create_playlist and /modify_playlist tests - /delete_playlist tests (success, not found) - /rename_playlist tests (success, not found) - /add_to_playlist tests (success, not found) - /run_playlist tests (disconnected, during homing) - /skip_pattern tests (success, no playlist) 16 tests total, all passing * ci(backend-testing-01): add GitHub Actions workflow for tests - Triggers on push to main/feature branches and PRs - Runs unit tests with CI=true (skips hardware tests) - Generates coverage report with pytest-cov - Uploads coverage to Codecov - Includes Ruff linting job (continue-on-error) - Uses Python 3.11 with pip caching * test(backend-testing-01): add integration test skeleton for hardware - Add conftest.py with hardware detection fixtures - Add test_hardware.py with @pytest.mark.hardware tests - Tests auto-skip without --run-hardware flag - Tests auto-skip in CI (when CI=true) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(integration): expand hardware tests with movement and pattern execution Fixes: - Status query: Don't assume Idle state, accept any valid GRBL status - Soft reset: Auto-detect firmware (FluidNC=$Bye, GRBL=Ctrl+X) New tests: - test_firmware_detection: Detect FluidNC vs GRBL firmware - test_homing_sequence: Full homing cycle with position verification - test_move_to_perimeter: Move ball to rho=1.0 - test_move_to_center: Move ball to rho=0.0 - test_execute_star_pattern: Run star.thr pattern end-to-end - test_websocket_status_endpoint: Test /ws/status WebSocket - test_position_saved_on_disconnect: Verify state persistence Total: 13 integration tests (all skip without --run-hardware) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(integration): add playback controls and playlist tests Playback controls (test_playback_controls.py): - TestPauseResume: pause_during_pattern, resume_after_pause - TestStop: stop_during_pattern, force_stop, pause_then_stop - TestSpeedControl: set_speed_during_playback, speed_bounds, change_speed_while_paused - TestSkip: skip_pattern_in_playlist, skip_while_paused Playlist tests (test_playlist.py): - TestPlaylistModes: single_mode, loop_mode, shuffle - TestPlaylistPause: pause_between_patterns, stop_during_playlist_pause - TestPlaylistClearPattern: playlist_with_clear_pattern - TestPlaylistStateUpdates: current_file_updates, playlist_index_updates, progress_updates - TestWebSocketStatus: status_updates_during_playback Total: 33 integration tests (all skip without --run-hardware) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: add testing guide README Includes: - Quick start commands - Test structure overview - Unit vs integration test instructions - Coverage report generation - CI behavior explanation - Examples for adding new tests - Troubleshooting section Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(test): account for angular_homing_offset_degrees in homing test The homing sequence sets theta to the configured offset (e.g., 135°), not 0. Test now compares against state.angular_homing_offset_degrees. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(test): wait for idle after move instead of sleep Movement tests now use check_idle_async() to properly wait for the machine to complete the move, instead of unreliable time.sleep(2). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: move_to_center and move_to_perimeter wait for idle before returning API endpoints now call check_idle_async(timeout=60) after move_polar to ensure the machine has completed the movement before returning success. This gives the frontend accurate feedback that the move is complete. Tests updated to use the API endpoints directly instead of calling move_polar + manual idle check. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(test): remove unsupported timeout arg from receive_json() FastAPI TestClient's WebSocket receive_json() doesn't accept timeout. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(test): fix WebSocket status format and add fast test speed - WebSocket returns {'type': 'status_update', 'data': {...}} Tests now check message.get("data") for status fields - Add autouse fixture to set speed=500 for faster integration tests - Restores original speed after each test Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: preserve playlist state when async task is cancelled by TestClient Root cause: FastAPI TestClient cancels async background tasks when HTTP requests complete, causing playlist state to be cleared before tests could verify it. Changes: - playlist_manager: Set all state vars (playlist_mode, current_playlist_index, current_playing_file) BEFORE creating async task for immediate visibility - pattern_manager: Handle CancelledError specially to preserve state when task is externally cancelled (vs normal completion or user stop) - pattern_manager: Only clear current_playing_file in stop_actions() when clear_playlist=True, since caller sets it immediately after otherwise - pattern_manager: Fix Python 3.9 compatibility (asyncio.timeout -> wait_for) - main.py: Skip endpoint proactively advances state when task not running - main.py: Fix HTTPException being incorrectly wrapped in 500 error - tests: Fix pattern path check (./patterns/ prefix was missing) - tests: Add reset_asyncio_events fixture to handle event loop isolation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: stop_execution and send_coordinate wait for idle before returning - stop_actions() now waits for hardware to reach idle state (30s timeout) - send_coordinate endpoint waits for idle after move (60s timeout) - Clear stop_requested flag before idle check to allow check_idle_async to work This ensures API responses only return after the machine has physically stopped moving, consistent with move_to_center and move_to_perimeter. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(01-01): install Vitest and React Testing Library - Add vitest, @vitest/ui, jsdom as dev dependencies - Add @testing-library/react, @testing-library/jest-dom, @testing-library/user-event - Create vitest.config.ts with jsdom environment, globals, and coverage - Create src/test/setup.ts with jest-dom matchers and cleanup - Add test scripts: test, test:watch, test:ui, test:coverage * chore(01-01): install and configure Playwright - Add @playwright/test as dev dependency - Install Chromium browser for E2E testing - Create playwright.config.ts with chromium project, webServer, and CI settings - Add test:e2e and test:e2e:ui scripts * chore(01-01): configure MSW for API mocking - Add msw as dev dependency for mocking API requests - Create src/test/mocks/handlers.ts with mock endpoints for patterns, playlists, status - Create src/test/mocks/server.ts with MSW server setup - Update src/test/setup.ts to start/stop MSW server and reset handlers between tests * test(01-01): add sample tests and TypeScript types - Create src/__tests__/sample.test.tsx to verify Vitest + RTL + jest-dom work - Create e2e/sample.spec.ts to verify Playwright configuration - Add vitest/globals to TypeScript types for test globals (describe, it, expect) * chore(01-01): add @vitest/coverage-v8 for coverage reports - Add @vitest/coverage-v8@3.2.4 to match vitest version - npm run test:coverage now generates v8 coverage reports * chore(01-01): ignore frontend test artifacts - Add frontend/coverage/ for Vitest coverage reports - Add frontend/playwright-report/ for Playwright HTML reports - Add frontend/test-results/ for Playwright test results * docs(01): complete test-infrastructure phase - Vitest configured with jsdom, RTL, coverage (INF-1) - Playwright installed with Chrome configuration (INF-2) - MSW configured for API mocking (INF-3) - Directory structure established (INF-4) All 4 must-haves verified. 2 component tests + 1 E2E test passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(02-01): add test utilities and expanded MSW handlers - Create renderWithProviders helper with BrowserRouter wrapper - Add mock data generators for patterns, playlists, and status - Expand MSW handlers for all component endpoints (50+ handlers) - Add pattern, playlist, playback, and table control endpoints - Create MockWebSocket class for WebSocket testing - Add browser API mocks (IntersectionObserver, ResizeObserver, canvas) - Update test setup with browser mocks and data reset * test(02-01): add component tests for critical pages BrowsePage tests: - Pattern listing renders from API - Search filters patterns by name - Empty state and error handling - Pattern selection opens sheet PlaylistsPage tests: - Playlist listing and selection - Create/edit/delete buttons present - Run playlist triggers API - Pattern count display TableControlPage tests: - Renders all control sections (Home/Stop/Reset/Speed) - Movement controls call correct APIs - Speed input submits on Enter and button click - Dialog trigger has correct aria attributes NowPlayingBar tests: - Visibility prop handling - Props acceptance without crashing - onClose callback handling Test utilities: - Updated setup.ts for WebSocket mocking - Changed onUnhandledRequest to 'warn' for WebSocket compatibility * docs(02-01): complete component-tests phase Tasks completed: 6/6 - Test utilities module with renderWithProviders - Expanded MSW handlers (50+ endpoints) - WebSocket mock utility - Browser API mocks (IntersectionObserver, canvas, localStorage) - Component tests for BrowsePage, PlaylistsPage, TableControlPage, NowPlayingBar - Test verification with 42 passing tests SUMMARY: .planning/phases/02-component-tests/02-01-SUMMARY.md * chore(03-01): add integration test infrastructure - Add apiCallLog tracking for verifying API call sequences - Add resetApiCallLog() to reset between tests - Add logApiCall() to key handlers (run_theta_rho, playlists, playback) - Update test setup to reset API call log in beforeEach - Add renderApp() helper for full app integration tests * test(03-01): add pattern flow integration tests - Test browse -> select -> run pattern flow - Verify API call (run_theta_rho) with correct file parameter - Test search -> filter -> run filtered pattern - Verify mock state updates after pattern starts - Verify API call logging with timestamp and method * test(03-01): add playlist flow integration tests - Test view and select playlist flow - Verify run_playlist API call with correct playlist_name - Test queue population from playlist files - Test create playlist via dialog - Test delete playlist with confirmation - Fix preview_thr_batch handler to accept file_names parameter * test(03-01): add playback flow integration tests - Test pattern playback lifecycle (start/stop) - Test playlist playback with queue population - Test stop_execution API resets all playback state - Verify state transitions (idle -> running -> stopped) - Verify API call sequences for pattern and playlist runs * docs(03-01): complete integration tests phase Tasks completed: 5/5 - Integration test infrastructure (apiCallLog, renderApp) - Pattern flow tests (6 tests) - Playlist flow tests (8 tests) - Playback flow tests (8 tests) SUMMARY: .planning/phases/03-integration-tests/03-01-SUMMARY.md * test(04-01): add Playwright API mock utilities - Add mock data for patterns, playlists, and status - Implement setupApiMocks() for route interception - Add getMockStatus/setMockStatus for state verification - Support pattern, playlist, and playback control endpoints * test(04-01): add pattern flow E2E tests - Test pattern list display on browse page - Test pattern selection opens detail panel - Test pattern execution triggers running state - Test search filtering functionality * test(04-01): add playlist flow E2E tests - Test playlist list display - Test playlist selection and execution - Test navigation between browse and playlists pages * test(04-01): add table control E2E tests - Test control page displays buttons - Test home action can be triggered - Test navigation bar shows all page links * test(04-01): update sample spec with infrastructure tests - Test app loads and renders header - Test bottom navigation is visible - Test dark mode toggle presence * ci(04-01): extend workflow for frontend tests - Add frontend-test job for Vitest tests - Add frontend-e2e job for Playwright tests - Update paths trigger to include frontend files - Configure Node.js 20 with npm caching - Install Playwright browsers in CI - Upload Playwright report on failure * fix(04-01): fix E2E tests and add WebSocket mocking - Add WebSocket mocking for /ws/status, /ws/logs, /ws/cache-progress - Fix Playwright config to use port 5174 to avoid conflicts - Add static file and additional API endpoint mocks - Fix pattern-flow test to use exact button name - Fix playlist-flow test to use title selector for Run button * docs(04-01): complete E2E and CI phase Tasks completed: 7/7 - Playwright API mock utilities with WebSocket support - Pattern flow E2E tests (4 tests) - Playlist flow E2E tests (3 tests) - Table control E2E tests (3 tests) - Updated sample spec (3 tests) - Extended CI workflow for frontend tests - Fixed E2E tests and WebSocket mocking SUMMARY: .planning/phases/04-e2e-ci/04-01-SUMMARY.md * add gitignore * feat: add sensor homing failure recovery popup When sensor homing fails during startup or manual homing: - Show a blocking popup notifying user to check sensor position - Provide "Retry Sensor Homing" option - Provide "Switch to Crash Homing" option - Connection is not established until user takes action - Add /recover_sensor_homing API endpoint for recovery Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: resolve TypeScript errors in test files - Remove unused 'screen' import from NowPlayingBar.test.tsx - Add missing IntersectionObserver properties to MockIntersectionObserver - Use type-only imports for PatternMetadata, PreviewData in handlers.ts - Use type-only imports for RenderOptions, ReactElement, ReactNode in utils.tsx - Export IntegrationWrapper to resolve unused variable warning Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add GRBL Hold and Alarm state recovery during pattern execution When the GRBL controller enters Hold state (e.g., from serial byte corruption triggering '!' command) or Alarm state, the timeout recovery logic now properly handles these states instead of failing after multiple retries. - Hold state: sends '~' (cycle start) to resume motion - Alarm state: sends '$X' (unlock) to clear fault condition - Both states now detected as valid status responses during recovery Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: define v3 requirements for touch app CPU optimization 16 requirements across 5 categories: - QML logging cleanup (6) - Timer optimization (2) - WebSocket optimization (2) - Preview cache (2) - Verification (4) Target: <20% idle CPU on Pi 3B+, Pi 4, Pi 5 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: create v3 roadmap with single-phase CPU optimization Phase 1: CPU Optimization - 16 requirements covered (100%) - QML logging cleanup, timer optimization, WebSocket, preview cache - Target: <20% idle CPU on Pi 3B+, Pi 4, Pi 5 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(01): create CPU optimization execution plan 6 tasks covering 16 requirements: - Remove QML console.log spam (5 tasks) - Optimize backend timer, WebSocket, preview cache (1 task) Target: <20% idle CPU on Pi 3B+, Pi 4, Pi 5 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * perf(01-01): remove MouseArea console.log spam in main.qml - Remove console.log from onPressed handler - Remove console.log from onPositionChanged handler - Remove console.log from onClicked handler - Keep backend.resetActivityTimer() calls for screen timeout * perf(01-01): remove remaining debug logs from main.qml - Remove console.log from onCurrentPageIndexChanged - Remove console.log from onShouldNavigateToExecutionChanged - Remove console.log from onExecutionStarted - Remove console.log from onScreenStateChanged - Remove console.log from onBackendConnectionChanged - Remove console.log from onRetryConnection - Remove console.log from StackLayout.onCompleted - Remove console.log from onTabClicked * perf(01-01): remove debug logs from ConnectionStatus.qml - Remove all console.log statements from color binding - Remove onSerialConnectionChanged debug handler - Remove Component.onCompleted debug handler - Remove onBackendChanged debug handler - Simplify color binding to single-line expression * perf(01-01): remove debug logs from ExecutionPage.qml - Remove onBackendChanged debug handler - Remove Component.onCompleted debug handler - Remove onSerialConnectionChanged debug handler - Remove onConnectionChanged debug handler - Remove console.log from onExecutionStarted - Remove console.log from Image source binding - Remove onStatusChanged debug handler - Remove onSourceChanged debug handler - Simplify Image source binding * perf(01-01): remove debug logs from remaining QML files TableControlPage.qml: - Remove console.log from signal handlers ModernPlaylistPage.qml: - Remove console.log from onSelectedPlaylistChanged - Remove Component.onCompleted debug handler - Remove console.log from playlist execution - Remove console.log from shuffle toggle - Remove console.log from run mode and clear pattern handlers ThemeManager.qml: - Remove console.log from onDarkModeChanged BottomNavTab.qml: - Remove console.log from icon mapping * perf(01-01): optimize timer, WebSocket, and preview cache in backend.py Timer optimization (REQ-TIMER-01, REQ-TIMER-02): - Replace 1-second continuous polling with event-driven single-shot timer - Timer now fires once after timeout duration, not every second - _reset_activity_timer restarts timer with full timeout - Renamed _check_screen_timeout to _screen_timeout_triggered WebSocket optimization (REQ-WS-01, REQ-WS-02): - Remove print statements from pattern change detection - Remove print statements from pause state changes - Remove print statements from serial connection changes - Remove print statements from speed changes - Only emit signals when values actually change (existing behavior) Preview cache (REQ-CACHE-01, REQ-CACHE-02): - Add _preview_cache dictionary in __init__ - Check cache before filesystem lookup in _find_pattern_preview - Cache positive results after successful lookup - Add _clear_preview_cache method for cache invalidation * docs(01): complete CPU optimization phase Phase 1 verified: 6/6 must-haves passed (code inspection) Code changes complete: - Removed 50+ console.log statements from QML files - Event-driven screen timeout (single-shot timer) - WebSocket signal optimization - Pattern preview path caching Pending: Hardware verification on Pi (5 requirements) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: stop tracking .planning directory Files were tracked before .gitignore entry was added. Removing from index only - files remain locally. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): eliminate CPU busy-wait in touch monitor thread The touch monitor thread was using a 10ms polling loop (100 iterations/sec) while waiting for touch input, causing 100% CPU usage when screen was off. Fixed by: - Using select() with 1-second timeout instead of busy polling - Removed time.sleep() calls that created artificial delays - Changed evtest subprocess to binary mode for select() compatibility This should reduce idle CPU from 100%+ to under 10% when screen is off. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(led): turn off LEDs during Still Sands when table goes idle Extended start_idle_led_timeout() to handle Still Sands LED control: - Now checks if in scheduled pause period with LED control enabled - Turns off LEDs instead of showing idle effect during Still Sands - Added check_still_sands parameter for cases where caller handles logic This fixes LEDs not turning off when table goes idle during Still Sands period (pattern stops, skips, completes, or playlist ends). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): resolve 100% CPU usage with qasync event loop pattern Root cause: The QEventLoop + run_forever() pattern in qasync causes CPU spinning. Combined with hoverEnabled MouseArea generating continuous events on capacitive touchscreens. Changes: - main.py: Use qasync.run() with async_main() pattern instead of QEventLoop.run_forever() - this properly yields to Qt event loop - main.qml: Remove hoverEnabled and onPositionChanged from MouseArea to prevent continuous event generation on touch displays - backend.py: Add 100ms throttling to _reset_activity_timer() as defense-in-depth against any remaining event storms - requirements.txt: Bump qasync to >=0.28.0 for latest fixes This supersedes the previous fix in c2b1851 which addressed a symptom (touch monitor thread) rather than the root cause (event loop pattern). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(dw): update touch app dependencies during dw update The previous touch app update logic did a redundant git pull (code is already part of main repo), but didn't update pip dependencies. This caused issues when requirements.txt changed (e.g., qasync version bump). Now properly: - Updates pip dependencies from requirements.txt - Restarts the touch app service to apply changes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): use proper qasync event wait pattern The previous fix used a polling loop with app.processEvents() which caused RuntimeError when aiohttp tasks tried to run concurrently. The issue: manually calling processEvents() inside an async function creates reentrant async execution, conflicting with other tasks. Fix: Use asyncio.Event with app.aboutToQuit signal instead of polling. qasync handles Qt/asyncio integration internally - we just await the quit signal without manual event processing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): add proper logging to touch monitoring - Add logger to backend.py (was using print() which journald doesn't capture) - Add logging to _screen_timeout_triggered, _start_touch_monitoring - Simplify _monitor_touch_input with proper select() non-blocking I/O - Remove unused touch-monitor script code path - Use binary mode for evtest subprocess to work with select() This will help diagnose touch-to-wake issues and ensure the flow is visible in systemd journal logs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): restore QEventLoop pattern for proper QTimer support The qasync.run() + await quit_event.wait() pattern doesn't properly process QTimer.singleShot callbacks, which broke touch-to-wake (the callback to start touch monitoring never fired). Restored the original QEventLoop + run_forever() pattern which properly integrates Qt timers. Using qasync 0.28.0 which should have fixes for the CPU spin issues reported in earlier versions. This should fix touch-to-wake while maintaining reasonable CPU usage. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * revert(touch): revert CPU optimization attempts - none resolved 100% CPU Reverting to e5265ac state. The following approaches were tried but did not fix the 100% CPU usage issue: ## Approach 1: Remove QML console.log statements - Removed 50+ console.log from main.qml, ExecutionPage.qml, ConnectionStatus.qml, ModernPlaylistPage.qml, TableControlPage.qml, ThemeManager.qml, BottomNavTab.qml - Result: Did not fix CPU issue ## Approach 2: Remove MouseArea hover events - Removed hoverEnabled and onPositionChanged from main.qml MouseArea - Theory: Capacitive touchscreens generate continuous hover events - Result: Did not fix CPU issue ## Approach 3: Event-driven screen timeout timer - Changed from 1-second polling loop to single-shot QTimer - Timer fires once after timeout instead of every second - Result: Did not fix CPU issue ## Approach 4: Touch monitor thread select() optimization - Changed from 10ms busy-polling to select() with 1-second timeout - Used binary mode for evtest subprocess - Result: Did not fix CPU issue ## Approach 5: qasync event loop pattern changes - Tried qasync.run() + async_main() instead of QEventLoop.run_forever() - Bumped qasync to >=0.28.0 - Result: Broke touch-to-wake (QTimer callbacks didn't fire) ## Approach 6: asyncio.Event wait pattern - Used asyncio.Event with app.aboutToQuit signal - Avoided manual processEvents() to prevent reentrant async execution - Result: Did not fix CPU issue ## Approach 7: Activity timer throttling - Added 100ms throttle to _reset_activity_timer() - Result: Did not fix CPU issue ## Approach 8: Restored QEventLoop pattern - Restored QEventLoop + run_forever() for proper QTimer support - Result: Fixed touch-to-wake but CPU issue remained Root cause still unknown. Need fresh investigation approach. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): resolve 100% CPU on screen timeout with proper thread cleanup Root cause: Touch monitoring thread had blocking readline() that couldn't exit when screen woke up, plus missing cleanup in _turn_screen_on(). Changes: - Add threading.Event stop flag for clean thread signaling - Use select() with 0.5s timeout for non-blocking reads - Add thread cleanup in _turn_screen_on() with join timeout - Add finally block for guaranteed subprocess termination - Check stop flag during all delays and loops Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): add CPUQuota limit and fix evtest binary mode buffering - Add CPUQuota=25% to systemd service as hard limit safety net - Switch evtest to binary mode to fix select() buffering issues - Skip evtest initialization output before monitoring for events - Prevents tight loop during evtest startup device info dump Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(touch): disable touch monitoring to verify 100% CPU hypothesis Temporarily disable touch monitoring on screen timeout to confirm that evtest subprocess is the root cause of 100% CPU usage. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(touch): add full-page pattern selector and enhance playlist management Replace the pattern selector popup with a full-page navigation that mirrors the Browse page layout. Patterns already in the playlist are highlighted with a blue border and checkmark badge for easy identification. Key changes: - Add PatternSelectorPage.qml with grid layout and instant visual feedback - Update ModernPlaylistPage to navigate to selector instead of popup - Add playlist creation/deletion buttons and pattern removal functionality - Enhance search with Enter-to-search pattern across pages - Add raw pattern tracking for proper API calls Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: remove dead /get_speed proxy and add missing /upload_theta_rho proxy - Remove /get_speed proxy entry that was never used by frontend or backend - Add /upload_theta_rho proxy for pattern file uploads Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): replace Material Icons delete button with Lucide SVG icon Material Icons font wasn't loading on Raspberry Pi. Lucide React icons are SVG-based and work reliably across all devices. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): improve text visibility in dark mode - Fix placeholderText color in ThemeManager (#606060 -> #9a9a9a) The old color was nearly invisible on dark backgrounds - Add placeholderTextColor to all search TextField components - Add proper text colors to PatternListPage search field - Add Components import alias to PatternListPage for ThemeManager access Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): improve dark mode visibility for buttons and text - Style search close (✕) buttons with proper themed colors - Add contentItem with ThemeManager colors for visibility - Add hover/press states using buttonBackgroundHover - Fix PlaylistPage.qml with full theme support: - Background colors, borders, text colors - Back button with proper contentItem - Fix PatternListPage "No patterns found" label color All flat buttons and text elements now use ThemeManager colors for proper visibility in both light and dark modes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): replace all Material Icons with Lucide SVG icons in TableControlPage Material Icons font doesn't load reliably on Raspberry Pi. Lucide React icons are bundled SVGs that work everywhere. Replaced ~30 icons including: - Loading spinners (sync → Loader2) - Navigation (home, back arrows) - Actions (power, restart, delete, send) - Status indicators (check, warning) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): replace all Material Icons with Lucide SVG icons in PlaylistsPage Replaced ~25 icons including: - Navigation (add, back, close) - Actions (play, save, edit, delete, shuffle, repeat) - Content (playlist, folder, music, image) - Feedback (check, search, sort arrows) Material Icons font doesn't load reliably on Raspberry Pi. Lucide React icons are bundled SVGs that work everywhere. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(frontend): replace all Material Icons with Lucide SVG icons in Layout Replace bottom navigation icons and all remaining Material Icons in Layout.tsx with Lucide React icons. This ensures icons render properly on Raspberry Pi which has issues loading the Material Icons web font. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): fix invisible button icons in QML touch app - Add color: "white" to ModernControlButton icon Text (was defaulting to black) - Replace 🗑 emoji with ✕ symbol for delete button (emoji not in Pi fonts) - Revert unnecessary frontend Lucide icon changes (3 commits) Fixes Shutdown Pi button and Delete Playlist button visibility on Pi. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): remove unsupported power icon, make delete button red - Remove ⏻ icon from Shutdown Pi button (not in Pi fonts) - Change delete playlist button to always red (#dc2626) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(touch): add iconSize property to ModernControlButton Allows independent control of icon size vs text size. Usage: iconSize: 24 (defaults to fontSize + 2 if not set) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): increase icon sizes on TableControlPage buttons Added iconSize: 20 to all buttons with icons for better visibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(touch): persist playlist settings with new defaults Settings now saved to touch_settings.json and remembered between sessions: - Shuffle: default ON - Run mode: default LOOP - Pause between patterns: default 3 HOURS - Clear pattern: default ADAPTIVE Backend changes: - Added playlistShuffle, playlistRunMode, playlistClearPattern properties - Added setPlaylist* slots to save settings - Updated _load/_save_local_settings for playlist settings QML changes: - Radio buttons now reflect loaded settings (checked bindings) - All controls call backend to persist changes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(touch): replace print statements with proper logging - Added Python logging module with INFO level by default - Converted 227 print statements to appropriate log levels: - DEBUG: Verbose info (API requests/responses, file searches, screen state) - INFO: Normal operations (connections, pattern execution, settings changes) - WARNING: Non-critical issues (timeouts, missing resources) - ERROR: Failures and exceptions - Removed emojis from log messages for cleaner output - Log format: HH:MM:SS [LEVEL] message To enable debug logging, set: logging.getLogger("DuneWeaver").setLevel(logging.DEBUG) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(touch): remove console.log debug statements from QML Removed 73 verbose debug logs from QML files: - main.qml: navigation, screen state, touch events - ConnectionStatus.qml: backend state logging - BottomNavTab.qml: icon value logging - ThemeManager.qml: dark mode toggle - TableControlPage.qml: serial connection state - ModernPlaylistPage.qml: playlist operations - ExecutionPage.qml: image loading, execution signals - PatternSelectorPage.qml: pattern selection QML doesn't support log levels, so debug output is removed entirely. For debugging, re-add console.log statements as needed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): fix syntax error in ModernPlaylistPage.qml Removed orphaned object literal code left behind from console.log removal. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(touch): fix shuffle toggle and improve stop reliability - Increase stop timeout from 10s to 45s to account for backend's idle check (10s lock + 30s idle wait) - Fix shuffle toggle breaking QML binding by updating backend directly instead of assigning to bound property - Remove ~200 lines of dead Python touch monitoring code since QML's global MouseArea handles wake-on-touch Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ui): add draggable now playing button and optimize logo uploads - Now Playing button can be dragged to snap to left, center, or right - Position persists across sessions via localStorage - Touch and mouse support with 8px drag threshold - Increase logo upload limit from 5MB to 10MB - Auto-optimize uploaded logos: resize to 512px max, convert to WebP - Typical 95%+ file size reduction for large images - SVG files pass through unchanged Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(pwa): iOS safe area handling and PWA icon transparency - Add env(safe-area-inset-bottom) to main content bottom padding in Layout to prevent content from being hidden behind nav bar on iPhone - Increase base bottom padding from 5rem to 8rem to clear floating Now Playing pill button - Add safe area inset subtraction to viewport height calculations in PlaylistsPage, LEDPage, and Now Playing bar expanded state - Fix PWA icon generation to composite onto solid #0a0a0a background, preventing iOS from showing white behind transparent custom logos - Add maskable purpose icon entries to web manifest for better Android adaptive icon support - Add hard_reset_theta setting for optional machine reset on theta normalization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): add custom day selector and fix time input overlap in Still Sands Add day-of-week toggle buttons when "Custom" is selected in the Days dropdown, and fix time inputs overlapping on mobile by adding overflow handling and explicit width. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(lint): resolve Ruff errors in dune-weaver-touch - Remove unused imports: QTouchEvent, QMouseEvent, QQmlContext (F401) - Move load_dotenv() call after all imports to fix E402 - Remove f-string prefix from strings with no placeholders (F541) - Replace bare except with except Exception (E722) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): wrap MQTT buttons on mobile to prevent overflow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(lint+test): remove unused imports, fix bare except, update delete button tests Ruff fixes: - Remove unused imports: Response, atexit, Tuple, Dict, Any, Union (main.py) - Remove unused Tuple import (png_cache_manager.py) - Remove unused Signal import (pattern_model.py, playlist_model.py) - Replace bare except with except Exception (dune-weaver-touch/main.py) Test fixes: - Update playlist delete button selectors to match Trash2 lucide icon (component switched from material-icons to lucide-react Trash2) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: add pre-commit hook for Ruff lint and frontend tests - Runs Ruff on staged .py files, blocks commit on lint errors - Runs vitest on staged .ts/.tsx files, blocks commit on test failures - Gracefully skips if ruff or node_modules not available - Auto-installs via npm prepare script - Shareable hook in scripts/pre-commit Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Improve ETA accuracy with rho-weighted time estimation This is the same change from PR#107, applied to the feature/react-ui branch. I have not tested this branch so please review. The ETA calculation on the Live Pattern Preview window is erratic, often jumping around by minutes at a time +/-. This is especially noticeable when there are a lot of small moves near the center of the pattern. This pull request replaces rate-based estimation with an algorithm that: * Weights coordinates by rho position (center moves are slower) * Smooths the rate using exponential moving average (alpha=0.02) * Excludes pause time from calculations * Requires 100 coords and 10 seconds before showing estimates The weight formula 1/(rho+0.15) accounts for polar geometry where moves near center cover less linear distance per theta change. In my limited testing this does smooth out the ETA significantly and makes it less prone to large increases. Additional testing and validation is recommended. This patch was written with the assistance of Claude Code * feat(ui+led): add log search, fix PWA toast positioning, and respect LED power state on Still Sands exit Add real-time search filtering to the log drawer (by message/logger), use CSS env(safe-area-inset-top) for Sonner toasts instead of hardcoded offset to fix Dynamic Island obstruction in PWA, and prevent LEDs from auto-powering on after Still Sands when no playing/idle effect is configured so manually-set effects persist through scheduled pause cycles. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): correct "Clear Sideway" typo to "Clear Sideways" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: add CONTRIBUTING.md and update README Add a contributing guide covering dev setup, testing (unit, frontend, e2e, hardware integration), linting, branch/commit conventions, the Vite proxy gotcha for new API endpoints, and fork-based PR workflow. Point contributors to the Discord #dev channel. Update README with refreshed content, swap hero image to og-image.jpg, and link the Contributing section to the new in-repo guide. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(nginx): add missing endpoint proxies to prevent 405 errors add_to_queue, restart_connection, controller_restart, recover_sensor_homing, run_theta_rho_file, download, check_software_update, and update_software were missing from the nginx proxy allowlist, causing POST requests to fall through to the static file handler which returns 405 Method Not Allowed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ui): add update notification indicator and version link - Add download icon with blue pulse dot in header when updates are available - Make "Latest Version" in Settings a clickable link to GitHub releases - Revert VERSION to 3.5.0 for pre-merge state - Update docker-compose.yml image tags from :feature-react-ui to :main Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * update version --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: PxT <paul@droflet.net>
  • Просмотр сравнение для этих 2 коммитов »

17 часов назад

dyadmisha синхронизированные коммиты с feature/react-ui на dyadmisha/dune-weaver из зеркала

  • 9c585ffe16 update version
  • d2418bea9e Merge origin/main into feature/react-ui Resolved 3 conflicts integrating bug fixes from main: - connection_manager.py: Added self.ws = None after close (NoneType fix) - state.py: Added shuffle property alongside event-based execution control - pattern_manager.py: Kept feature branch's comprehensive retry/recovery logic Also fixed pre-existing ruff lint issues in staged files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 714672344e feat(ui): add update notification indicator and version link - Add download icon with blue pulse dot in header when updates are available - Make "Latest Version" in Settings a clickable link to GitHub releases - Revert VERSION to 3.5.0 for pre-merge state - Update docker-compose.yml image tags from :feature-react-ui to :main Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 61c5f3bf60 fix(nginx): add missing endpoint proxies to prevent 405 errors add_to_queue, restart_connection, controller_restart, recover_sensor_homing, run_theta_rho_file, download, check_software_update, and update_software were missing from the nginx proxy allowlist, causing POST requests to fall through to the static file handler which returns 405 Method Not Allowed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • c9218274db docs: add CONTRIBUTING.md and update README Add a contributing guide covering dev setup, testing (unit, frontend, e2e, hardware integration), linting, branch/commit conventions, the Vite proxy gotcha for new API endpoints, and fork-based PR workflow. Point contributors to the Discord #dev channel. Update README with refreshed content, swap hero image to og-image.jpg, and link the Contributing section to the new in-repo guide. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • Просмотр сравнение для этих 117 коммитов »

17 часов назад

dyadmisha синхронизированные коммиты с main на dyadmisha/dune-weaver из зеркала

1 неделя назад

dyadmisha синхронизированные коммиты с feature/react-ui на dyadmisha/dune-weaver из зеркала

  • 44a52af395 Add missing getter functions for pattern_lock and pause_event These functions are called by main.py and playlist_manager.py but were missing from the reverted pattern_manager.py. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 5315670e47 Revert to stable serial/motion code from commit 3143609 Reverts complex timeout recovery and retry logic that was causing issues. Keeps working features from HEAD: - get_last_completed_execution_time() for historical ETA - connect_device() with DW LED support and auto-connect modes - MPos/WPos dual format support for GRBL compatibility - DEPRIORITIZED_PORTS for smarter port selection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • a2692651e4 Fix infinite loop when machine stays in Run state Add max_run_extensions limit (10) to prevent infinite timeout loop when machine continuously reports 'Run' status. Previously, the code would reset the timeout indefinitely as long as the machine was running. Now after 10 extensions (20+ minutes total), the pattern will stop with a clear error message instead of looping forever. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 08b6c4d760 Add .vite/ to gitignore Vite's cache directory should not be committed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • be0690acc4 Revert process isolation and real-time scheduling (commit 5a8643c) Remove ProcessPoolExecutor and real-time scheduling features that were causing issues on some systems: - Remove modules/core/process_pool.py - Remove modules/core/scheduling.py - Revert cache_manager.py to use asyncio.to_thread - Revert preview.py to use asyncio.to_thread - Remove CPU pinning and priority elevation from motion/LED threads Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • Просмотр сравнение для этих 9 коммитов »

1 неделя назад

dyadmisha синхронизированные коммиты с feature/react-ui на dyadmisha/dune-weaver из зеркала

  • 1ab1f4679f Add comprehensive logging to timeout recovery for diagnosis Enhances the timeout recovery section with detailed logging to help diagnose why recovery fails in some cases (user reported GRBL was Idle but recovery didn't detect it). New logging includes: - Failed G-code command and retry counts - Connection type and state validation - Buffer clear confirmation and bytes waiting - Each response received during recovery (at INFO level) - Summary of all responses received - Clear failure summary with possible causes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 50e4927409 Add timeout recovery logic for lost 'ok' responses on Pi 3B+ When a 120s timeout occurs waiting for 'ok', the code now attempts recovery: - Sends status query '?' to check if machine is still responsive - If machine is Idle: assumes command completed, 'ok' was lost - continues pattern - If machine is Run: extends timeout as movement is still in progress - If delayed 'ok' received during recovery: accepts it and continues - If no response: retries the command (up to 2 times) before stopping This handles cases where the serial 'ok' response is completely lost due to UART timing issues on Pi 3B+, without unnecessarily stopping patterns. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • f8889dbb33 Add serial corruption retry logic for Pi 3B+ UART timing issues - Add reset_input_buffer() method to SerialConnection for clearing stale data - Clear serial input buffer before sending G-code commands - Add 5ms post-send delay for UART buffer stabilization - Implement retry logic (up to 3 retries) for corruption-type GRBL errors (error:1, error:2, error:20-23 indicate syntax errors from bit flips) - Throttle WebSocket status polling during pattern execution (2s vs 1s) - Detect MSG:ERR: Bad GCode messages as corruption indicators This addresses serial corruption on Pi 3B+ where G-code commands get garbled (e.g., G53 → G5s) due to UART timing issues under asyncio load. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • Просмотр сравнение для этих 3 коммитов »

1 неделя назад

dyadmisha синхронизированные коммиты с feature/react-ui на dyadmisha/dune-weaver из зеркала

  • e1e70bc13a Revert termios modifications - may cause serial corruption The termios changes (disabling ECHO, ICANON) may be causing serial data corruption (G1 -> O1). Main branch doesn't have these modifications and works fine. The FluidNC echo is handled in pattern_manager.py by ignoring echoed G-code commands, so termios-level echo suppression is not needed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 2ce38dd635 Disable SCHED_RR - causes serial buffer corruption on Pi 3B+ The real-time scheduling (SCHED_RR priority 60 + CPU 0 pinning) appears to cause serial buffer corruption on Pi 3B+, resulting in: - Commands being merged (e.g., "G1 G53" -> "G10G53") - GRBL errors from corrupted commands - Pattern execution failures This is separate from the FluidNC echo issue (which main branch handled silently). The corruption is timing-related and specific to certain Pi models. Keeping disabled until we can investigate proper CPU affinity settings that don't interfere with serial I/O. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 867b90a22e Handle FluidNC command echo gracefully FluidNC firmware echoes commands back before sending 'ok'. Instead of logging warnings for each echo, silently skip echoed G-code commands (G0, G1, G2, G3, $J, M) and continue reading to get the actual 'ok' response. This reduces log spam while maintaining proper error detection for actual GRBL errors and alarms. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 382806095b Fix serial echo causing GRBL communication failure on Pi 3B+ Root cause: On Pi 3B+ with /dev/ttyAMA0, the serial port had echo enabled at the TTY level. This caused: 1. Sent G-code commands echoed back as "responses" 2. Motion thread waiting for 'ok' but receiving its own commands 3. Buffer corruption merging commands (G1 G53 -> G10G53) 4. GRBL error from corrupted command, stopping pattern Fix: Disable ECHO and related flags via termios when opening the serial connection. This ensures raw serial communication without any TTY processing that could interfere. Also re-enables real-time scheduling which wasn't the cause. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • eb619c0895 TEMP: Disable real-time scheduling to test Pi 3B+ serial timeout Hypothesis: SCHED_RR priority 60 + CPU 0 pinning may be blocking serial interrupt handling on Pi 3B+, causing the motion thread to never receive 'ok' responses from GRBL. CPU 0 typically handles hardware interrupts including serial ports. Running a real-time thread there might starve the interrupt handler. This is a test commit - will be reverted or made configurable based on results. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • Просмотр сравнение для этих 13 коммитов »

1 неделя назад

dyadmisha синхронизированные коммиты с master на dyadmisha/esphome-stream-server из зеркала

  • 7546679e35 Fix compatibility with ESPHome 2026.1 The getpeername() function has been removed and replaced with getpeername_to(), which writes into a caller-owned span instead.

1 неделя назад

dyadmisha синхронизированные коммиты с develop на dyadmisha/AI-on-the-edge-device из зеркала

1 неделя назад

dyadmisha синхронизированные коммиты с main на dyadmisha/dune-weaver из зеркала

  • ef8787a6c1 Revert retry timeout - wait indefinitely for GRBL 'ok' GRBL only sends 'ok' after a move completes, which can take many seconds at slow speeds. The 1-second timeout was causing premature resends and duplicate commands. Reverted to original behavior: wait indefinitely for 'ok' response. Added stop_requested checks so patterns can still be cancelled. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • fc4287a1cc Add retry logic for motion commands with 1-second timeout - Wait up to 1 second for 'ok' response after sending G-code - Automatically resend command if no response received - Retries forever until 'ok' is received - Prevents silent hang if response is missed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • d103a6fb90 Fix NoneType context manager error in connection manager Removed unsafe `self.lock = None` in close() methods that caused "'NoneType' object does not support the context manager protocol" errors when status queries ran after connection close. Added connection validity check in get_status_response() for defense. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 2c75c085a7 update DAGGKAPRIFOL config
  • Просмотр сравнение для этих 4 коммитов »

1 неделя назад

dyadmisha синхронизированные коммиты с feature/react-ui на dyadmisha/dune-weaver из зеркала

  • 10be8dbd62 Fix UI showing stale countdown after skip during pause Clear both pause_time_remaining and original_pause_time immediately when skip breaks the pause loop. Previously original_pause_time wasn't cleared until the next pattern started, causing the UI to show stale countdown state. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 8707c4ed58 Remove dangerous lock=None in connection close methods Setting self.lock = None after close() caused race conditions: - Motion thread calls readline() with "with self.lock:" - If close() was called, lock is None - AttributeError is caught, motion thread retries forever - Pattern hangs waiting for "ok" that never comes This was a regression not present in main branch. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 50df3a3ec7 Fix CPU spin loop in motion thread readline wait Added sleep(0.01) after readline() to prevent 100% CPU usage when readline() returns empty (timeout or bad serial state). Without this, the inner while loop would spin continuously. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 3b4f60ca66 Update package-lock.json dependencies Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 5b7804685b Fix serial stability issues caused by asyncio event overhead - Make stop_requested/skip_requested setters thread-safe using call_soon_threadsafe() for cross-thread event manipulation - Remove state.stop_requested=False from move_polar() which was triggering event manipulation thousands of times per pattern - Add stop_requested clearing to manual move endpoints instead (/move_to_center, /move_to_perimeter, /send_coordinate) - Fix BrowsePage upload refresh to call fetchPatterns() The root cause was move_polar() setting stop_requested on every coordinate, causing constant asyncio event manipulation that created race conditions and overhead during pattern execution. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • Просмотр сравнение для этих 66 коммитов »

1 неделя назад

dyadmisha синхронизированные коммиты с feature/react-ui на dyadmisha/dune-weaver из зеркала

  • 9af82531e4 Fix stale "Waiting for next pattern" UI after skipping pause Clear pause_time_remaining and original_pause_time when a new pattern starts executing, not just after the pause loop ends. This prevents stale waiting state from showing in the UI if skip was triggered during a pause period. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

2 недель назад

dyadmisha синхронизированные коммиты с feature/react-ui на dyadmisha/dune-weaver из зеркала

  • 485e189a32 Reduce default process pool workers for low-RAM devices Default to 1 worker instead of (cpu_count - 1) to conserve RAM on memory-constrained devices like Pi Zero 2 W (512MB). This prevents memory pressure that causes UI sluggishness and unresponsive stops. Added POOL_WORKERS env var to override if more workers are needed on systems with more RAM. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

2 недель назад

dyadmisha синхронизированные коммиты с develop на dyadmisha/AI-on-the-edge-device из зеркала

2 недель назад

dyadmisha синхронизированные новые ссылки develop к dyadmisha/AI-on-the-edge-device из зеркала

2 недель назад

dyadmisha синхронизированные коммиты с read на dyadmisha/dune-weaver из зеркала

  • c59b8c1c6c Improve dw update with proper container restart and cleanup - Stop container before pulling new image (docker compose down) - Use --remove-orphans to clean up removed services - Add docker image/container prune after update to free disk space Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 5a8643c593 Fix motion/LED stutter via process isolation and real-time scheduling (#103) * Add UART QoS for motion control thread * Add CPU isolation for preview threads (CPUs 1-3) * Use ProcessPoolExecutor to eliminate GIL contention * Dynamic CPU detection for worker count and affinity * Consolidate process pools into single shared pool * Extract process pool to dedicated module * refactor: centralize thread scheduling in modules/core/scheduling.py * remove throttling delays - QoS measures are sufficient * docs: update process_pool docstring for motion/LED * fix: use ProcessPoolExecutor initializer to avoid nice accumulation * fix: setup realtime priority from within thread to avoid native_id race * refactor: reuse parse_theta_rho_file instead of duplicated logic * refactor: move sched_param struct to module level * fix: use asyncio.get_running_loop() instead of deprecated get_event_loop() * fix: use get_running_loop() instead of deprecated get_event_loop() in main.py * refactor: remove redundant _parse_file_in_process wrapper * perf: cache libc handle at module level * fix: remove duplicate priority elevation log * fix: use parse_theta_rho_file instead of undefined _parse_file_in_process * fix: prevent nice accumulation in lower_priority() * docs: restore 300x300 optimization note in preview docstring * feat: motion thread priority (60) > LED (40) for CNC reliability * Pin FastAPI main process to CPUs 1-N, reserve CPU 0 for motion/LED * Add semaphore to limit concurrent preview processing to 5 requests * Add helper to combine file read and base64 encode in executor * Use semaphore and executor helper in preview batch endpoint * Add macOS Finder file to .gitignore
  • 6d89559607 Improve firmware detection and fix G-code command reliability - Add FluidNC firmware detection via $I command with version logging - Use targeted FluidNC queries ($/axes/x/steps_per_mm) instead of $$ for better reliability - Fall back to GRBL $$ command with retries when FluidNC queries fail - Fix infinite loop bug in send_grbl_coordinates() - now has proper 30s timeout - Add alarm state handling - proceeds with settings queries even when limit switch active - Use G53 (machine coordinates) for zeroing positions instead of unsupported G52 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 314360968e Update machine position after homing completes The async position update in check_idle() was silently failing because the event loop was already closed. Now uses synchronous get_machine_position() to query hardware and save state after successful homing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • 7eae12e951 update gitignore
  • Просмотр сравнение для этих 10 коммитов »

2 недель назад