{printName}
)}
{printer.model || 'Unknown Model'}
{/* Nozzle Info - only in expanded */}
{viewMode === 'expanded' && status?.nozzles && status.nozzles[0]?.nozzle_diameter && (
• {status.nozzles[0].nozzle_diameter}mm
)}
{viewMode === 'expanded' && maintenanceInfo && maintenanceInfo.total_print_hours > 0 && (
Are you sure you want to delete "{printer.name}"? This will remove all connection settings.
{getStatusDisplay(status.state, status.stg_cur_name)}
)}{status.stg_cur_name || 'Printing'}
{status.subtask_name || status.current_print}
Status
{getStatusDisplay(status.state, status.stg_cur_name)}
Last: {lastPrint.print_name || lastPrint.filename} {lastPrint.completed_at && ( • {formatDateOnly(lastPrint.completed_at, { month: 'short', day: 'numeric' })} )}
) : (Ready to print
)} > )}L / R
{Math.round(status.temperatures.nozzle || 0)}° / {Math.round(status.temperatures.nozzle_2 || 0)}°
> ) : ( <>Nozzle
{Math.round(status.temperatures.nozzle || 0)}°C
> )}Bed
{Math.round(status.temperatures.bed || 0)}°C
Chamber
{Math.round(status.temperatures.chamber || 0)}°C
L
Nozzle
R
{printer.ip_address}
{printer.serial_number}
Calibration Required
Please ensure the build plate is completely empty, then click Calibrate.
Calibration captures a reference image of the empty plate. Future checks will compare against this reference to detect objects.
Tip: You can store up to 5 calibrations for different plates. The system automatically uses the best match when checking.
{plateCheckResult.is_empty ? 'Plate appears empty' : 'Objects detected on plate'}
Confidence: {Math.round(plateCheckResult.confidence * 100)}% | Difference: {plateCheckResult.difference_percent.toFixed(1)}%
Analysis preview:
Green box = detection area, Red overlay = differences from calibration
{plateCheckResult.message}
> )} {/* Saved References Grid */} {plateReferences && plateReferences.references.length > 0 && (Saved References ({plateReferences.references.length}/{plateReferences.max_references})
setEditingRefLabel({ index: ref.index, label: ref.label })} title={ref.label ? `${ref.label} - Click to edit` : 'Click to add label'} > {ref.label || No label}
)} {/* Timestamp */}{ref.timestamp ? new Date(ref.timestamp).toLocaleDateString() : ''}
Detection Area (ROI)
{!editingRoi ? ( ) : (Adjust the detection area to focus on the build plate. The green box in the preview shows the current area.
Current: X={Math.round((plateCheckResult.roi?.x || 0.15) * 100)}%, Y={Math.round((plateCheckResult.roi?.y || 0.35) * 100)}%, W={Math.round((plateCheckResult.roi?.w || 0.70) * 100)}%, H={Math.round((plateCheckResult.roi?.h || 0.55) * 100)}%
)}No objects found
Objects are loaded when a print starts
Match IDs with your printer display
The printer screen shows object IDs on the build plate
Wait for layer 2+ to skip objects (currently layer {status?.layer_num ?? 0})
Docker detected. Enter your printer's subnet in CIDR notation.
Requires network_mode: host in docker-compose.yml.
{printer.name || printer.serial}
{mapModelCode(printer.model) || 'Unknown'} • {printer.ip_address} {printer.serial.startsWith('unknown-') && ( • Serial required )}
{isDocker ? 'Scanning subnet for Bambu printers...' : 'Scanning network...'}
)} {hasScanned && !discovering && discovered.length === 0 && (No printers found{isDocker ? ' in the specified subnet' : ' on the network'}.
)} {hasScanned && !discovering && discovered.length > 0 && newPrinters.length === 0 && (All discovered printers are already configured.
)}{printer.name}
{uploadStatus.message}
{uploadStatus.error && ({uploadStatus.error}
)}Firmware uploaded to SD card!
To apply the update on your printer: