Committed and Pushed by ButtonClick
This commit is contained in:
135
programs/screenShot.js
Executable file
135
programs/screenShot.js
Executable file
@@ -0,0 +1,135 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { exec } = require('child_process');
|
||||
const { logSnapshot } = require('./log');
|
||||
|
||||
|
||||
function snapshot(outDir, cam0, cam1, ws){
|
||||
|
||||
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
|
||||
const picDate = Date.now();
|
||||
const name0 = `snapshot_video0_${picDate}.jpg`;
|
||||
const name1 = `snapshot_video1_${picDate}.jpg`;
|
||||
cam0.snapshot(path.join(outDir, name0));
|
||||
cam1.snapshot(path.join(outDir, name1));
|
||||
|
||||
|
||||
strFile0 = path.join(outDir, name0);
|
||||
strFile1 = path.join(outDir, name1);
|
||||
|
||||
const relUrl = `/snapshots/${name0}`;
|
||||
const relUrlApp = `/snapshots/${name0.replace('.jpg','_two_cam_annotated.jpg')}`;
|
||||
// The Python postprocessor writes an overlay named "_two_cam_overlay.png" and a CSV named "_two_cam.csv"
|
||||
const relOverlay = `/snapshots/${name0.replace('.jpg','_two_cam_overlay.png')}`;
|
||||
const relOverlayCSV = `/snapshots/${name0.replace('.jpg','_two_cam.csv')}`;
|
||||
|
||||
const annotatedPath = path.join(outDir, name0.replace('.jpg','_two_cam_annotated.jpg'));
|
||||
const overlayPath = path.join(outDir, name0.replace('.jpg','_two_cam_overlay.png'));
|
||||
const csvPath = path.join(outDir, name0.replace('.jpg','_two_cam.csv'));
|
||||
|
||||
|
||||
|
||||
const command = `python3 /usr/src/app/programs/readTwoImages.py -i ${strFile0} -i ${strFile1} -npz /usr/src/app/data/settings/callibration_cam0.npz -npz /usr/src/app/data/settings/callibration_cam1.npz -settings /usr/src/app/data/settings/settings.json`;
|
||||
console.log("Executing Python " + command);
|
||||
|
||||
// Run the Python post-processing and send the snapshot response only
|
||||
// after the annotated files are present to avoid transient 404s in the browser.
|
||||
exec(command, (error, stdout, stderr) => {
|
||||
try {
|
||||
if (error) {
|
||||
console.error(`Error: ${error.message}`);
|
||||
// Capture which generated files actually exist for debugging
|
||||
const files = {
|
||||
annotated: fs.existsSync(annotatedPath),
|
||||
overlay: fs.existsSync(overlayPath),
|
||||
csv: fs.existsSync(csvPath)
|
||||
};
|
||||
// Log full details server-side for diagnosis
|
||||
const detailed = {
|
||||
type: 'snapshot',
|
||||
ok: false,
|
||||
error: error.message,
|
||||
stdout: String(stdout).slice(0, 4096),
|
||||
stderr: String(stderr).slice(0, 4096),
|
||||
files
|
||||
};
|
||||
logSnapshot(command, JSON.stringify(detailed));
|
||||
|
||||
// Send a short, user-friendly error to the client (no large stdout/stderr)
|
||||
const shortError = String(stderr || error.message || '').includes('Corrupt JPEG')
|
||||
? 'postprocessor failed: corrupt JPEG input'
|
||||
: 'postprocessor failed';
|
||||
try { ws.send(JSON.stringify({ type: 'snapshot', ok: false, error: shortError })); } catch (e) {}
|
||||
return;
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
// Log stderr but don't fail outright; sometimes tools output warnings on stderr.
|
||||
if (String(stderr).trim()) console.error(`Stderr: ${stderr}`);
|
||||
}
|
||||
|
||||
console.log(`Output:\n${stdout}`);
|
||||
|
||||
// Wait up to ~1s (10 * 100ms) for the generated files to appear on disk.
|
||||
const waitForFiles = (paths, attempts = 10, delayMs = 100) => new Promise((resolve) => {
|
||||
let tries = 0;
|
||||
(function poll() {
|
||||
const ok = paths.every(p => fs.existsSync(p));
|
||||
if (ok || tries >= attempts) return resolve(ok);
|
||||
tries++;
|
||||
setTimeout(poll, delayMs);
|
||||
})();
|
||||
});
|
||||
|
||||
waitForFiles([annotatedPath, overlayPath, csvPath]).then((found) => {
|
||||
if (!found) {
|
||||
const files = {
|
||||
annotated: fs.existsSync(annotatedPath),
|
||||
overlay: fs.existsSync(overlayPath),
|
||||
csv: fs.existsSync(csvPath)
|
||||
};
|
||||
// Log details server-side
|
||||
const detailed = {
|
||||
type: 'snapshot',
|
||||
ok: false,
|
||||
url: relUrl,
|
||||
urlApp: relUrlApp,
|
||||
overlay: relOverlay,
|
||||
overlayCSV: relOverlayCSV,
|
||||
files
|
||||
};
|
||||
logSnapshot(command, JSON.stringify(detailed));
|
||||
// Send a concise error to the client
|
||||
try { ws.send(JSON.stringify({ type: 'snapshot', ok: false, error: 'postprocessor incomplete (missing outputs)' })); } catch (e) {}
|
||||
return;
|
||||
}
|
||||
|
||||
const response = JSON.stringify({
|
||||
type: 'snapshot',
|
||||
ok: found,
|
||||
url: relUrl,
|
||||
urlApp: relUrlApp,
|
||||
overlay: relOverlay,
|
||||
overlayCSV: relOverlayCSV
|
||||
});
|
||||
logSnapshot(command, response);
|
||||
try { ws.send(response); } catch (e) {}
|
||||
}).catch((waitErr) => {
|
||||
console.error('waitForFiles failed:', waitErr);
|
||||
const response = JSON.stringify({ type: 'snapshot', ok: false, error: String(waitErr) });
|
||||
logSnapshot(command, response);
|
||||
try { ws.send(response); } catch (e) {}
|
||||
});
|
||||
} catch (handlerErr) {
|
||||
console.error('snapshot handler error:', handlerErr);
|
||||
const response = JSON.stringify({ type: 'snapshot', ok: false, error: String(handlerErr) });
|
||||
logSnapshot(command, response);
|
||||
try { ws.send(response); } catch (e) {}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
module.exports = { snapshot };
|
||||
Reference in New Issue
Block a user