Skip to content

feat: comprehensive multi-printer support, RTSP streaming, headless mode, and codebase quality improvements#9

Merged
GhostTypes merged 12 commits into
mainfrom
multi-printer-etc
Oct 18, 2025
Merged

feat: comprehensive multi-printer support, RTSP streaming, headless mode, and codebase quality improvements#9
GhostTypes merged 12 commits into
mainfrom
multi-printer-etc

Conversation

@GhostTypes

Copy link
Copy Markdown
Member

Summary

This major feature release introduces complete multi-printer connection management, RTSP camera streaming capabilities, headless server operation mode, per-printer configuration settings, and extensive codebase quality improvements including dead code removal and comprehensive documentation.

Key Features

Multi-Printer Architecture

Implemented context-based architecture enabling simultaneous monitoring and control of multiple FlashForge 3D printers:

  • PrinterContextManager: Singleton manager for creating and tracking multiple printer contexts, each with isolated backend, polling service, camera proxy, and connection state
  • MultiContextPollingCoordinator: Dynamic polling frequency adjustment
  • PrinterTabsComponent: Tabbed UI component for seamless switching between connected printers
  • PortAllocator: Automatic unique camera proxy port allocation per context (8181-8191 range)
  • All IPC handlers now support optional contextId parameter for multi-context operations
  • WebUI fully supports multi-printer operations and context switching

RTSP Camera Support

Full RTSP camera support with configurable quality settings:

  • RtspStreamService: Manages RTSP streams using ffmpeg-based transcoding to MPEG1
  • Each printer context receives unique WebSocket port (9000-9009) for isolated streaming
  • JSMpeg integration for browser-compatible MPEG1 playback (vendored locally for offline support)
  • Per-printer frame rate (1-60 fps) and quality (1-5) configuration
  • Automatic stream type detection (MJPEG vs RTSP) with appropriate player selection
  • Robust process cleanup with timeout handling and proper signal management
  • Desktop application and WebUI both support RTSP cameras seamlessly

Headless Mode

  • HeadlessManager: Orchestrates printer connections and lifecycle management
  • Command-line argument support for flexible deployment:
    • --last-used: Auto-connect to last used printer
    • --all-saved-printers: Connect to all saved printers with IP discovery
    • --printers=: Direct connection with explicit IP/type/check-code specifications
  • HeadlessLogger: Structured file-based logging for server environments
  • HeadlessDetection: Mode-aware service initialization
  • WebUI always available in headless mode with configurable host/port
  • Multi-printer support through ConnectionFlowManager integration

Per-Printer Configuration

Extended printer settings system for customization:

  • Per-printer custom camera URL and enable/disable toggle
  • Per-printer custom LED control enable/disable
  • Force legacy mode per-printer override
  • RTSP frame rate and quality settings per printer
  • Settings persist across reconnections in printer_details.json
  • Real-time settings updates through IPC system
  • Settings UI integration in settings window

Codebase Quality Improvements

  • Documentation: Added comprehensive @fileoverview JSDoc headers to 113 TypeScript files across all major subsystems
  • Dead Code Analysis: Integrated Knip tooling with configuration for Electron's multi-entry-point architecture
  • Cleanup: Removed unused legacy files (dom.utils.ts, printer-polling.ts, validation schemas)
  • Dependencies: Removed 6 unused dependencies (axios, p-limit, express-ws, webpack-dev-server, forge fuses packages)
  • Type Safety: Added TypeScript declaration files for JSMpeg and node-rtsp-stream
  • Linting: Enhanced ESLint configuration with TypeScript project support, resolved all linter errors
  • Code Standards: Strengthened typing throughout (IPC handlers, dynamic imports, service interfaces)

Technical Details

Architecture Changes

  • Services (CameraProxyService, ConnectionStateManager, PrinterPollingService) are now fully context-aware with per-context instances
  • Event system enhanced with context identification for proper UI routing
  • Connection flow initializes per-printer settings with smart defaults
  • WebUI API routes support multi-context operations
  • Camera setup is context-aware with per-context RTSP streams

Files Changed

  • 153 files modified
  • 20,643 insertions, 15,597 deletions

New Components

  • src/managers/PrinterContextManager.ts - Context lifecycle management
  • src/managers/HeadlessManager.ts - Headless mode orchestration
  • src/services/MultiContextPollingCoordinator.ts - Multi-context polling coordination
  • src/services/RtspStreamService.ts - RTSP streaming management
  • src/types/PrinterContext.ts - Context type definitions
  • src/ipc/printer-context-handlers.ts - Context-specific IPC handlers
  • src/ipc/handlers/printer-settings-handlers.ts - Per-printer settings IPC
  • src/ui/components/printer-tabs/ - Tabbed interface component with documentation
  • src/utils/PortAllocator.ts - Port allocation utility with comprehensive tests
  • src/utils/HeadlessArguments.ts - Command-line argument parsing
  • src/utils/HeadlessDetection.ts - Headless mode detection
  • src/utils/HeadlessLogger.ts - Structured logging for headless environments
  • src/types/jsmpeg.d.ts - JSMpeg TypeScript declarations
  • src/types/node-rtsp-stream.d.ts - node-rtsp-stream TypeScript declarations

Dependencies Added

  • @cycjimmy/jsmpeg-player - MPEG1 video decoding
  • node-rtsp-stream - RTSP to MPEG1 transcoding
  • knip - Dead code analysis

Dependencies Removed

  • axios - Unused HTTP client
  • express-ws - Unused WebSocket support
  • p-limit - Unused concurrency limiter
  • @electron-forge/plugin-fuses - Unused build plugin
  • @electron/fuses - Unused security configuration
  • @types/express-ws - Unused type definitions
  • webpack-dev-server - Unused development server

Add comprehensive multi-printer connection support with context-based
architecture allowing simultaneous monitoring and control of multiple
FlashForge 3D printers.

Core Features:
- PrinterContextManager: Singleton manager for creating and tracking
  multiple printer contexts, each with isolated backend, polling service,
  camera proxy, and connection state
- MultiContextPollingCoordinator: Dynamic polling frequency adjustment
  (active contexts: 3s, inactive: 3s for TCP keep-alive)
- PrinterTabsComponent: Tabbed UI for switching between connected printers
- PortAllocator: Unique camera proxy port allocation per context (8181-8191)

Architecture Changes:
- All IPC handlers now support optional contextId parameter
- Services (CameraProxyService, ConnectionStateManager, PrinterPollingService)
  are context-aware with per-context instances
- Event system enhanced with context identification for proper UI routing
- WebUI API routes support multi-context operations and switching

New Files:
- src/managers/PrinterContextManager.ts - Context lifecycle management
- src/services/MultiContextPollingCoordinator.ts - Multi-context polling
- src/types/PrinterContext.ts - Context type definitions
- src/ipc/printer-context-handlers.ts - Context IPC handlers
- src/ui/components/printer-tabs/ - Tabbed interface component
- src/utils/PortAllocator.ts - Port allocation utility with tests
- ai_specs/HEADLESS_MODE_IMPLEMENTATION_PLAN.md - Updated for multi-printer

Documentation:
- Updated CLAUDE.md with multi-printer architecture overview
- Added development patterns and testing checklist
- Documented key file locations and context-aware operation patterns

Testing Status:
- Type checking: Passed
- Code structure: Follows established patterns
- Runtime testing: Required before production use
Implement headless mode to run FlashForgeUI without a GUI, enabling server-only
operation with WebUI access. This allows deployment scenarios where a headless
machine manages multiple printers remotely.

Key additions:
- HeadlessManager for lifecycle management and connection orchestration
- Command-line argument parsing with support for --last-used, --all-saved-printers,
  --printers=, and WebUI configuration
- HeadlessDetection utility for mode-aware service initialization
- HeadlessLogger for structured file-based logging
- HeadlessArguments for configuration validation and parsing

Connection features:
- Auto-connect from saved printers with IP discovery/update
- Direct connection with explicit IP/type/check-code specs
- Multi-printer support via ConnectionFlowManager extensions

Infrastructure changes:
- Skip UI-dependent services (notifications, main window) in headless mode
- WebUI always starts in headless mode with configurable host/port
- Process lifecycle management (no quit on window close in headless)

Documentation:
- HEADLESS.md with comprehensive usage guide and examples
- Cleaned up obsolete ai_specs plan files (implementation complete)
…tion

This commit implements full RTSP camera streaming support using node-rtsp-stream and JSMpeg, extends the multi-printer architecture with per-printer configuration settings, and fixes WebUI build process issues.

RTSP Streaming:
- Added RtspStreamService for managing RTSP streams with ffmpeg-based transcoding to MPEG1
- Each printer context gets unique WebSocket port (9000-9009) for RTSP streaming
- Implemented explicit ffmpeg process cleanup with SIGKILL on stream stop
- Desktop app and WebUI both support RTSP cameras via JSMpeg player
- Added stream type detection (MJPEG vs RTSP) in camera-utils

Per-Printer Settings:
- Extended PrinterDetails type with per-printer settings: customCameraEnabled, customCameraUrl, customLedsEnabled, forceLegacyMode
- Settings are preserved across reconnections and persist in printer_details.json
- New printer-settings-handlers.ts for IPC operations
- Settings UI integration in settings window with real-time updates

WebUI Improvements:
- Fixed dev script to build WebUI files before starting watch mode
- Added canvas element for RTSP playback alongside img for MJPEG
- WebUI now supports both MJPEG and RTSP camera streams
- JSMpeg loaded via CDN for browser compatibility

Multi-Printer Integration:
- Camera setup now context-aware with per-context RTSP streams
- PrinterContextManager emits context-updated events for settings changes
- Connection flow initializes per-printer settings with defaults for new printers
- Headless mode supports per-printer settings
- Filament tracker API routes use active context (compatible with existing integrations)

Dependencies:
- Added @cycjimmy/jsmpeg-player for MPEG1 decoding
- Added node-rtsp-stream for RTSP to MPEG1 transcoding
- Added express-ws for WebSocket support
This commit addresses several issues with RTSP streaming, multi-printer context handling,
and WebUI integration:

RTSP Stream Service:
- Suppress verbose ffmpeg output using -nostats and -loglevel quiet flags
- Implement proper ffmpeg process cleanup with timeout and exit handling
- Fix process termination on Windows by using kill() without signal parameter

Multi-Printer Context Support:
- Fix pre-disconnect event to handle camera cleanup per context
- Update camera IPC handler to accept optional contextId parameter
- Add WebUI polling update forwarding for WebSocket clients
- Document filament tracker routes for active context behavior

WebUI Enhancements:
- Vendor JSMpeg library locally instead of using CDN for offline support
- Update build script to copy vendor libraries from node_modules
- Fix LED control visibility to support both built-in and legacy API modes

Configuration:
- Add npm run build:webui:* to Claude Code allowed commands
Add comprehensive @fileoverview JSDoc documentation headers to 113 TypeScript files
across all major subsystems following project documentation standards.

Coverage includes:
- IPC handlers (camera, dialogs, window control, backend/connection/control/job/material/webui handlers)
- Core managers (Config, ConnectionFlow, Loading, PrinterBackend, PrinterDetails)
- Services (connection, discovery, polling, thumbnails, notifications, UI updater, static files)
- Printer backends (AD5X, Adventurer5M/Pro, Base, DualAPI, GenericLegacy)
- Type definitions (camera, config, IPC, printer, backend operations, features)
- UI components (all dialog preload/renderer files, status, settings)
- Utilities (EventEmitter, printer/camera/DOM/error/extraction/time/validation utils)
- Validation schemas (config, job, printer)
- WebUI (server components, API routes, auth, schemas, types, static app)
- Window management (factories, manager, shared config/types)

Each header includes:
- Clear description of file purpose and functionality
- Key features and core responsibilities
- Exported functions, classes, types, and interfaces
- Architectural context and usage patterns

Also cleaned up obsolete planning documents (HEADLESS.md, RTSP_Integration_Plan.md)
and updated docs/README.md.

All documentation follows established project patterns and supports the npm run
docs:check validation workflow.
Add Knip configuration and comprehensive documentation for identifying
unused code, dependencies, and exports. Configure for Electron's
multi-entry-point architecture with main process, renderer processes,
preload scripts, and WebUI entry points.

Changes:
- Add .claude/commands/find-dead-code.md with detailed usage guide
- Add knip.json configured for Electron architecture
- Add npm scripts for various Knip analysis modes
- Whitelist Knip-related Bash commands in Claude settings
- Remove unused legacy files:
  - src/services/printer-polling.ts (backward compatibility)
  - src/utils/dom.utils.ts
  - src/validation/*-schemas.ts (config, job, printer)
- Remove unused dependencies:
  - axios, express-ws, p-limit
  - @electron-forge/plugin-fuses, @electron/fuses
  - @types/express-ws
  - webpack-dev-server

Configuration includes ignores for:
- Local file dependencies (ff-api, slicer-meta)
- Windows binaries (powershell)
- Test infrastructure imports
Detailed description:
- Add TypeScript declaration files for JSMpeg and node-rtsp-stream to provide safer typing in UI and RTSP services.
- Harden RTSP streaming lifecycle in `RtspStreamService`:
  - Use explicit ffmpeg process references, improved kill/timeout logic, and safer stream stop handling.
- Improve IPC and main process handling:
  - Strengthen dynamic import typings for connection and camera handlers.
  - Ensure platform-info is sent to renderer after it signals readiness to avoid race conditions.
  - Add PollingData typing where forwarded to WebUI.
- Update UI components:
  - Add JSMpeg integration using local types; tidy up camera preview initialization and teardown.
  - Mark internal maps/fields readonly to communicate immutability intent.
  - Remove stale title update logic from UI updater.
- Linting / build adjustments:
  - Add `project` to `.eslintrc.json` parserOptions to enable TypeScript rules.
  - Update `src/webui/static/tsconfig.json` to include local type file.
 - Resolved all linter errors
- Add AI spec docs for gridstack and RTSP configuration.
Add configurable RTSP streaming settings and fix Windows 11 notification system

Windows 11 Notification Fix:
- Fix AppUserModelId to match electron-builder appId (com.ghosttypes.flashforgeui)
- Notifications now work properly on Windows 11
- Add automatic icon path resolution for notification icons
- Platform-specific icon support (ICO for Windows, PNG for Linux)
- macOS uses bundle icon automatically (documented in code)
- Ensure NSIS creates shortcuts for proper notification support

RTSP Configuration:
- Add per-printer frame rate (1-60 fps) and quality (1-5) settings
- Expose settings in Settings UI with validation
- Pass configuration to RtspStreamService for customizable streaming
- Settings stored per-printer, take effect on next connection
- Increase Settings window size to accommodate new controls

The RTSP settings allow users to balance stream quality and performance
based on their network conditions.
Exposes process.platform directly via contextBridge as window.PLATFORM,
eliminating timing-dependent IPC events for platform detection. Platform
class is now applied synchronously when DOM loads.

Changes:
- Expose window.PLATFORM directly in preload (synchronous access)
- Apply platform-specific styling immediately in renderer
- Remove dependency on platform-info IPC event

Benefits:
- No race conditions or timing issues
- Platform info available before any async operations
- Simpler, more reliable code
…port

Replaced singleton notification coordinator with per-context architecture
to enable notifications for all connected printers simultaneously.

Key Changes:
- Created MultiContextNotificationCoordinator service for managing
  per-context PrinterNotificationCoordinator instances
- Each printer context now gets its own notification coordinator
  automatically when polling starts
- Notifications fire for ALL connected printers regardless of active tab
- Cleaned up AppUserModelId configuration (single call, all platforms)
- Removed unnecessary platform-specific console logging

Technical Implementation:
- Added notificationCoordinator field to PrinterContext interface
- Integrated coordinator creation in MultiContextPollingCoordinator
  when polling services start (line 270)
- Coordinators automatically disposed when contexts are removed
- Full type safety maintained, passes TypeScript compilation

This fixes notifications not working after multi-printer implementation
where the global coordinator was never connected to polling services.
Fixed race condition causing duplicate "printer cooled" notifications.
State flag is now updated before sending notification to prevent
multiple polling updates from triggering duplicate sends.
@GhostTypes GhostTypes self-assigned this Oct 18, 2025
@GhostTypes GhostTypes added the enhancement New feature or request label Oct 18, 2025
@GhostTypes GhostTypes merged commit d60d94e into main Oct 18, 2025
4 checks passed
@GhostTypes GhostTypes deleted the multi-printer-etc branch October 18, 2025 23:48
GhostTypes pushed a commit that referenced this pull request Dec 8, 2025
Updated transitive glob dependencies to resolve high severity
command injection vulnerability (GHSA-5j98-mcp5-4vw2).

The vulnerability affected glob CLI but not the programmatic API
used by config-file-ts and rimraf dependencies.

Fixes:
- Dependabot alert #8
- Dependabot alert #9
- Dependabot alert #10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant