Skip to content

Commit 9f4f31a

Browse files
committed
fix: Wire SpoolmanUsageTracker to PrintStateMonitor for filament deduction
PROBLEM: Users reported that Spoolman was not deducting filament usage after print completion, despite being able to see and select spools in the WebUI. ROOT CAUSE: The SpoolmanUsageTracker was never being created and wired to the PrintStateMonitor for each printer context. While the MultiContextSpoolmanTracker.createTrackerForContext() method existed, it was never called during initialization or when backends were created. This was identified by comparing with the FlashForgeUI-Electron codebase, which properly wires up the trackers in its backend-initialized event handler. SOLUTION: 1. Added backend-initialized event handler to create monitors when printers are connected dynamically (e.g., via API reconnect/discovery) 2. Added initializeMonitors() function to create monitors for printers connected during startup 3. Both paths now create: - PrintStateMonitor for each context - SpoolmanUsageTracker for each context (wired to PrintStateMonitor) The SpoolmanUsageTracker now properly listens to print-completed events and updates Spoolman server with filament usage data when prints finish. TESTING: - Filament deduction should now work for all connected printers - Usage is updated immediately when print completes - Works for both startup connections and dynamic connections
1 parent 07aaa64 commit 9f4f31a

1 file changed

Lines changed: 85 additions & 0 deletions

File tree

src/index.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,44 @@ function startPolling(): void {
235235
}
236236
}
237237

238+
/**
239+
* Initialize monitors for all connected contexts
240+
* Creates PrintStateMonitor and SpoolmanTracker for each context
241+
*/
242+
function initializeMonitors(): void {
243+
const printStateMonitor = getMultiContextPrintStateMonitor();
244+
const spoolmanTracker = getMultiContextSpoolmanTracker();
245+
246+
for (const contextId of connectedContexts) {
247+
try {
248+
const context = contextManager.getContext(contextId);
249+
const pollingService = context?.pollingService;
250+
251+
if (!pollingService) {
252+
console.error(`[Monitors] Missing polling service for context ${contextId}`);
253+
continue;
254+
}
255+
256+
// Create PrintStateMonitor
257+
printStateMonitor.createMonitorForContext(contextId, pollingService);
258+
const stateMonitor = printStateMonitor.getMonitor(contextId);
259+
260+
if (!stateMonitor) {
261+
console.error(`[Monitors] Failed to create print state monitor for ${contextId}`);
262+
continue;
263+
}
264+
265+
console.log(`[Monitors] Created PrintStateMonitor for context ${contextId}`);
266+
267+
// Create SpoolmanTracker (depends on PrintStateMonitor)
268+
spoolmanTracker.createTrackerForContext(contextId, stateMonitor);
269+
console.log(`[Monitors] Created SpoolmanTracker for context ${contextId}`);
270+
} catch (error) {
271+
console.error(`[Monitors] Failed to initialize monitors for context ${contextId}:`, error);
272+
}
273+
}
274+
}
275+
238276
/**
239277
* Initialize camera proxies for all connected contexts
240278
*/
@@ -434,12 +472,59 @@ async function main(): Promise<void> {
434472
});
435473
console.log('[Events] Post-connection hook configured');
436474

475+
// 12c. Setup backend-initialized hook to create monitors and trackers
476+
// This is critical for Spoolman deduction and print state monitoring
477+
connectionManager.on('backend-initialized', (event: unknown) => {
478+
const backendEvent = event as { contextId: string; modelType: string };
479+
const contextId = backendEvent.contextId;
480+
481+
console.log(`[Events] Backend initialized for context ${contextId}, creating monitors...`);
482+
483+
// Get context and polling service
484+
const context = contextManager.getContext(contextId);
485+
const pollingService = context?.pollingService;
486+
487+
if (!pollingService) {
488+
console.error('[Events] Missing polling service for context initialization');
489+
return;
490+
}
491+
492+
try {
493+
// Create PrintStateMonitor for this context
494+
const printStateMonitor = getMultiContextPrintStateMonitor();
495+
printStateMonitor.createMonitorForContext(contextId, pollingService);
496+
const stateMonitor = printStateMonitor.getMonitor(contextId);
497+
498+
if (!stateMonitor) {
499+
console.error('[Events] Failed to create print state monitor');
500+
return;
501+
}
502+
503+
console.log(`[Events] Created PrintStateMonitor for context ${contextId}`);
504+
505+
// Create SpoolmanTracker for this context (depends on PrintStateMonitor)
506+
const spoolmanTracker = getMultiContextSpoolmanTracker();
507+
spoolmanTracker.createTrackerForContext(contextId, stateMonitor);
508+
509+
console.log(`[Events] Created SpoolmanTracker for context ${contextId}`);
510+
} catch (error) {
511+
console.error(`[Events] Failed to create monitors for context ${contextId}:`, error);
512+
}
513+
});
514+
console.log('[Events] Backend-initialized hook configured');
515+
437516
// 13. Start polling for connected printers
438517
if (connectedContexts.length > 0) {
439518
startPolling();
440519
console.log(`[Init] Polling started for ${connectedContexts.length} printer(s)`);
441520
}
442521

522+
// 13b. Initialize monitors and trackers for connected printers
523+
if (connectedContexts.length > 0) {
524+
initializeMonitors();
525+
console.log(`[Init] Monitors initialized for ${connectedContexts.length} printer(s)`);
526+
}
527+
443528
// 14. Initialize camera proxies
444529
if (connectedContexts.length > 0) {
445530
await initializeCameraProxies();

0 commit comments

Comments
 (0)