From 49745249016e6798c3065fa02aa9e5646cfe5cf9 Mon Sep 17 00:00:00 2001 From: ganglyglub2-gif Date: Tue, 18 Nov 2025 12:54:19 -0600 Subject: [PATCH] =?UTF-8?q?Finalizar=20estilos=20de=20acorde=C3=B3n=20y=20?= =?UTF-8?q?correcci=C3=B3n=20de=20fuente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- www/index.php | 6 +-- www/procesar.php | 11 +++-- www/runPrusa.js | 104 +++++++++++++++++++++++++++++++++-------------- 3 files changed, 84 insertions(+), 37 deletions(-) diff --git a/www/index.php b/www/index.php index e51bef0..7ac793c 100644 --- a/www/index.php +++ b/www/index.php @@ -237,7 +237,7 @@ session_start();
-

Sube tu archivo .STL, selecciona la impresora y el material para obtener una cotización estimada.

+

Sube tu archivo (STL, STEP, OBJ, 3MF), selecciona la impresora y el material para obtener una cotización estimada.


@@ -255,8 +255,8 @@ session_start();
- - + +
diff --git a/www/procesar.php b/www/procesar.php index 1fd14b2..fda894f 100644 --- a/www/procesar.php +++ b/www/procesar.php @@ -27,7 +27,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { echo '
No se pudo leer la información del G-code.
'; exit; } - + // Capturamos el nombre del STL final (por si hubo conversión) + $nombreArchivoFinal = $result['finalStl'] ?? basename($stlPath); + // Datos del archivo $margen = 0.10; $filamento_mm = $result['filamentUsedMm'] ?? 0; @@ -152,7 +154,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {

'; - // ========= 2. BLOQUE DE ACORDEONES (REESTRUCTURADO LADO A LADO) ========= + // ========= 2. BLOQUE DE ACORDEONES ========= echo '
@@ -227,8 +229,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
'; - // === DIV OCULTO === - $stlUrl = 'uploads/' . htmlspecialchars(basename($stlPath)); + // === DIV OCULTO + + $stlUrl = 'uploads/' . htmlspecialchars($nombreArchivoFinal); echo ''; diff --git a/www/runPrusa.js b/www/runPrusa.js index 75ffaf0..5218a01 100644 --- a/www/runPrusa.js +++ b/www/runPrusa.js @@ -1,44 +1,88 @@ -const { exec } = require('child_process'); +const { execFile } = require('child_process'); const fs = require('fs'); const path = require('path'); -const stlFile = process.argv[2]; -if (!stlFile || !fs.existsSync(stlFile)) { - console.error(JSON.stringify({ error: 'Archivo STL no encontrado' })); +// Argumentos +const inputFile = process.argv[2]; +const profileName = process.argv[3]; + +// Validaciones iniciales +if (!inputFile || !fs.existsSync(inputFile)) { + console.error(JSON.stringify({ error: 'Archivo no encontrado' })); process.exit(1); } -const gcodeFile = stlFile.replace(/\.stl$/i, '.gcode'); +// Ruta al binario de PrusaSlicer +const prusaPath = '/app/squashfs-root/squashfs-root/usr/bin/prusa-slicer'; -// Ruta al perfil de PrusaSlicer -const profilePath = '/app/profiles/Ender3_Bltouch.ini'; +// Función principal asíncrona para manejar el flujo paso a paso +async function procesarArchivo() { + try { + let stlFile = inputFile; + const ext = path.extname(inputFile).toLowerCase(); + + // 1. SI NO ES STL, LO CONVERTIMOS + if (ext !== '.stl') { + // Creamos un nombre para el nuevo STL (ej: archivo.step -> archivo.stl) + const convertedStl = inputFile.substring(0, inputFile.lastIndexOf('.')) + '.stl'; + + // Comando de conversión: prusa-slicer --export-stl -o archivo.stl archivo.step + await new Promise((resolve, reject) => { + execFile(prusaPath, ['--export-stl', '-o', convertedStl, inputFile], (error, stdout, stderr) => { + if (error) reject(`Error convirtiendo a STL: ${stderr || error.message}`); + else resolve(); + }); + }); + + // Ahora usamos el nuevo archivo convertido para todo lo demás + stlFile = convertedStl; + } -// Ruta absoluta del binario -const prusaCmd = `/app/squashfs-root/squashfs-root/usr/bin/prusa-slicer --export-gcode -o ${gcodeFile} --load ${profilePath} ${stlFile}`; + // 2. PREPARAMOS EL G-CODE + const gcodeFile = stlFile.replace(/\.stl$/i, '.gcode'); + + // Perfil de impresora (Fallback si no se envía) + const profilePath = profileName + ? `/app/profiles/${profileName}` + : '/app/profiles/Ender3_Bltouch.ini'; -exec(prusaCmd, (error, stdout, stderr) => { - if (error) { - console.error(JSON.stringify({ error: `Error al generar G-code: ${error.message}`, stderr })); - return; - } + if (!fs.existsSync(profilePath)) { + throw new Error(`Perfil no encontrado: ${profilePath}`); + } - if (!fs.existsSync(gcodeFile)) { - console.error(JSON.stringify({ error: 'No se generó el archivo G-code' })); - return; - } + // 3. GENERAMOS EL G-CODE (Usando el STL, sea el original o el convertido) + await new Promise((resolve, reject) => { + const prusaArgs = ['--export-gcode', '-o', gcodeFile, '--load', profilePath, stlFile]; + execFile(prusaPath, prusaArgs, (error, stdout, stderr) => { + if (error) reject(`Error generando G-code: ${stderr || error.message}`); + else resolve(); + }); + }); - const gcodeContent = fs.readFileSync(gcodeFile, 'utf-8'); + if (!fs.existsSync(gcodeFile)) { + throw new Error('No se generó el archivo G-code'); + } - const filamentMatchMm = gcodeContent.match(/filament used \[mm\] = ([0-9.]+)/i); - const filamentMatchCm3 = gcodeContent.match(/filament used \[cm3\] = ([0-9.]+)/i); - const timeMatch = gcodeContent.match(/estimated printing time .* = ([0-9hms ]+)/i); + // 4. LEEMOS RESULTADOS + const gcodeContent = fs.readFileSync(gcodeFile, 'utf-8'); + const filamentMatchMm = gcodeContent.match(/filament used \[mm\] = ([0-9.]+)/i); + const filamentMatchCm3 = gcodeContent.match(/filament used \[cm3\] = ([0-9.]+)/i); + const timeMatch = gcodeContent.match(/estimated printing time .* = ([0-9hms ]+)/i); - const result = { - gcodeFile, - filamentUsedMm: filamentMatchMm ? parseFloat(filamentMatchMm[1]) : null, - filamentUsedCm3: filamentMatchCm3 ? parseFloat(filamentMatchCm3[1]) : null, - estimatedTime: timeMatch ? timeMatch[1].trim() : null - }; + // 5. ENVIAMOS LA RESPUESTA + // Importante: Devolvemos 'finalStl' para que PHP sepa qué archivo mostrar en el visor + console.log(JSON.stringify({ + gcodeFile: gcodeFile, + finalStl: path.basename(stlFile), // <--- ESTO ES CLAVE PARA EL VISOR + filamentUsedMm: filamentMatchMm ? parseFloat(filamentMatchMm[1]) : 0, + filamentUsedCm3: filamentMatchCm3 ? parseFloat(filamentMatchCm3[1]) : 0, + estimatedTime: timeMatch ? timeMatch[1].trim() : "0h 0m 0s" + })); - console.log(JSON.stringify(result)); -}); \ No newline at end of file + } catch (err) { + console.error(JSON.stringify({ error: err.message })); + process.exit(1); + } +} + +procesarArchivo(); \ No newline at end of file