Script Callibrate

This commit is contained in:
chk
2026-06-10 11:45:41 +02:00
parent e3e9aa5e37
commit 17e11d9993
4 changed files with 374 additions and 3 deletions

View File

@@ -6,6 +6,7 @@ import fs from 'fs';
import fsPromises from 'fs/promises';
import { fileURLToPath } from 'url';
import process from 'process';
import { spawn } from 'child_process';
import { WebcamClient } from './webcamClient.js';
const __filename = fileURLToPath(import.meta.url);
@@ -332,6 +333,79 @@ app.post('/api/calibration/foto', async (req, res) => {
}
});
/**
* POST /api/calibration/compute
* Führt scripts/callibriate.py für eine Kamera aus.
* Body: { camera: "cam0" }
* Antwortet als Server-Sent Events (SSE): jede Zeile stdout/stderr als
* data: {"type":"log","text":"..."}
* Abschluss:
* data: {"type":"done","exitCode":0}
*/
const PYTHON_BIN = process.env.PYTHON_BIN || 'python';
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' });
const session = await findLatestCalibSession();
if (!session) return res.status(400).json({ error: 'Keine Kalibrierungs-Session vorhanden' });
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();
const send = (obj) => 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: '' });
const proc = spawn(PYTHON_BIN, [
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 });
});
// 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}` });
});
proc.on('error', (err) => {
send({ type: 'log', text: `Fehler beim Starten: ${err.message}` });
send({ type: 'done', exitCode: -1 });
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();
});
});
async function checkServiceReachability(name, url) {
try {
const controller = new AbortController();