Fix
This commit is contained in:
116
server/server.js
116
server/server.js
@@ -346,64 +346,84 @@ const PYTHON_BIN = process.env.PYTHON_BIN || 'python3';
|
||||
const calibScriptPath = path.join(__dirname, '..', 'scripts', 'callibriate.py');
|
||||
|
||||
app.post('/api/calibration/compute', async (req, res) => {
|
||||
const { camera } = req.body ?? {};
|
||||
if (!camera) return res.status(400).json({ error: '"camera" parameter fehlt' });
|
||||
try {
|
||||
const { camera } = req.body ?? {};
|
||||
if (!camera) return res.status(400).json({ error: '"camera" parameter fehlt' });
|
||||
|
||||
const session = await findLatestCalibSession();
|
||||
if (!session) return res.status(400).json({ error: 'Keine Kalibrierungs-Session vorhanden' });
|
||||
const session = await findLatestCalibSession();
|
||||
if (!session) return res.status(400).json({ error: 'Keine Kalibrierungs-Session vorhanden' });
|
||||
|
||||
const sessionDir = path.join(calibDataDir, session);
|
||||
const sessionDir = path.join(calibDataDir, session);
|
||||
|
||||
// SSE-Header
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
res.flushHeaders();
|
||||
// SSE-Header – erst NACH den Validierungen senden
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
res.flushHeaders();
|
||||
|
||||
const send = (obj) => res.write(`data: ${JSON.stringify(obj)}\n\n`);
|
||||
// Schreibt nur wenn die Verbindung noch offen ist
|
||||
const send = (obj) => {
|
||||
if (!res.writableEnded) res.write(`data: ${JSON.stringify(obj)}\n\n`);
|
||||
};
|
||||
|
||||
send({ type: 'log', text: `▶ Session: ${session}` });
|
||||
send({ type: 'log', text: `▶ Kamera: ${camera}` });
|
||||
send({ type: 'log', text: `▶ Script: ${calibScriptPath}` });
|
||||
send({ type: 'log', text: '' });
|
||||
send({ type: 'log', text: `▶ Session: ${session}` });
|
||||
send({ type: 'log', text: `▶ Kamera: ${camera}` });
|
||||
send({ type: 'log', text: `▶ Script: ${calibScriptPath}` });
|
||||
send({ type: 'log', text: '' });
|
||||
|
||||
const proc = spawn(PYTHON_BIN, [
|
||||
calibScriptPath,
|
||||
'--camera', camera,
|
||||
'--input-dir', sessionDir,
|
||||
'--output-dir', sessionDir,
|
||||
]);
|
||||
// -u = unbuffered (Python gibt jede Zeile sofort aus)
|
||||
const proc = spawn(PYTHON_BIN, [
|
||||
'-u',
|
||||
calibScriptPath,
|
||||
'--camera', camera,
|
||||
'--input-dir', sessionDir,
|
||||
'--output-dir', sessionDir,
|
||||
]);
|
||||
|
||||
// stdout zeilenweise weiterleiten
|
||||
let stdoutBuf = '';
|
||||
proc.stdout.on('data', (chunk) => {
|
||||
stdoutBuf += chunk.toString();
|
||||
const lines = stdoutBuf.split('\n');
|
||||
stdoutBuf = lines.pop(); // letztes (unvollständiges) Fragment behalten
|
||||
for (const line of lines) send({ type: 'log', text: line });
|
||||
});
|
||||
let stdoutBuf = '';
|
||||
proc.stdout.on('data', (chunk) => {
|
||||
stdoutBuf += chunk.toString();
|
||||
const lines = stdoutBuf.split('\n');
|
||||
stdoutBuf = lines.pop();
|
||||
for (const line of lines) send({ type: 'log', text: line });
|
||||
});
|
||||
|
||||
// stderr als Warnung weiterleiten
|
||||
let stderrBuf = '';
|
||||
proc.stderr.on('data', (chunk) => {
|
||||
stderrBuf += chunk.toString();
|
||||
const lines = stderrBuf.split('\n');
|
||||
stderrBuf = lines.pop();
|
||||
for (const line of lines) send({ type: 'log', text: `[stderr] ${line}` });
|
||||
});
|
||||
let stderrBuf = '';
|
||||
proc.stderr.on('data', (chunk) => {
|
||||
stderrBuf += chunk.toString();
|
||||
const lines = stderrBuf.split('\n');
|
||||
stderrBuf = lines.pop();
|
||||
for (const line of lines) send({ type: 'log', text: `[stderr] ${line}` });
|
||||
});
|
||||
|
||||
proc.on('error', (err) => {
|
||||
send({ type: 'log', text: `Fehler beim Starten: ${err.message}` });
|
||||
send({ type: 'done', exitCode: -1 });
|
||||
res.end();
|
||||
});
|
||||
proc.on('error', (err) => {
|
||||
console.error('calibration/compute spawn error:', err);
|
||||
send({ type: 'log', text: `Fehler beim Starten: ${err.message}` });
|
||||
send({ type: 'done', exitCode: -1 });
|
||||
if (!res.writableEnded) res.end();
|
||||
});
|
||||
|
||||
proc.on('close', (code) => {
|
||||
if (stdoutBuf) send({ type: 'log', text: stdoutBuf }); // Rest ausgeben
|
||||
if (stderrBuf) send({ type: 'log', text: `[stderr] ${stderrBuf}` });
|
||||
send({ type: 'done', exitCode: code });
|
||||
res.end();
|
||||
});
|
||||
proc.on('close', (code) => {
|
||||
if (stdoutBuf) send({ type: 'log', text: stdoutBuf });
|
||||
if (stderrBuf) send({ type: 'log', text: `[stderr] ${stderrBuf}` });
|
||||
send({ type: 'done', exitCode: code ?? -1 });
|
||||
if (!res.writableEnded) res.end();
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
// Fehler VOR flushHeaders → normaler JSON-Fehler
|
||||
// Fehler NACH flushHeaders → SSE-Fehlerevent + close
|
||||
console.error('calibration/compute error:', err);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({ error: String(err) });
|
||||
} else {
|
||||
try {
|
||||
res.write(`data: ${JSON.stringify({ type: 'log', text: `Server-Fehler: ${err.message}` })}\n\n`);
|
||||
res.write(`data: ${JSON.stringify({ type: 'done', exitCode: -1 })}\n\n`);
|
||||
res.end();
|
||||
} catch { /* Verbindung bereits geschlossen */ }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function checkServiceReachability(name, url) {
|
||||
|
||||
Reference in New Issue
Block a user