Config Page

This commit is contained in:
chk
2026-06-07 10:03:34 +02:00
parent f205418640
commit faccbf55ce
16 changed files with 5375 additions and 69 deletions

View File

@@ -6,6 +6,7 @@ const http = require('http');
const path = require('path');
const { CameraSwitch } = require('./src/cameraSwitch');
const { createSnapshotRouter, createStreamRouter, createCamerasRouter } = require('./src/snapshotService');
const { createConfigRouter } = require('./src/configService');
const PORT = parseInt(process.env.PORT ?? '8444', 10);
const LIVE_SIZE = process.env.LIVE_SIZE ?? '640x480';
@@ -17,12 +18,20 @@ const ON_DEMAND = (process.env.ON_DEMAND ?? 'true') !== 'false'; // Live nur bei
const IDLE_GRACE_MS = parseInt(process.env.IDLE_GRACE_MS ?? '15000', 10);
// ── cameras.json → CameraSwitch-Instanzen ─────────────────────────────────────
const CAMERAS_PATH = path.join(__dirname, 'cameras.json');
let camerasJson;
try {
camerasJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'cameras.json'), 'utf8'));
camerasJson = JSON.parse(fs.readFileSync(CAMERAS_PATH, 'utf8'));
} catch (e) {
console.error('cameras.json fehlt oder ungültig:', e.message); process.exit(1);
}
// Atomar schreiben: tmp + rename → nie ein halb-geschriebenes cameras.json.
function persistCameras(obj) {
const tmp = CAMERAS_PATH + '.tmp';
fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\n', 'utf8');
fs.renameSync(tmp, CAMERAS_PATH);
}
const camsConfig = camerasJson.cameras;
if (!Array.isArray(camsConfig) || camsConfig.length === 0) {
console.error('cameras.json: "cameras" muss ein nicht-leeres Array sein'); process.exit(1);
@@ -43,6 +52,7 @@ for (const cam of camsConfig) {
hiresFps: cam.hiresFps ?? HIRES_FPS,
encode: cam.encode ?? ENCODE_MODE,
hiresEncode: cam.hiresEncode, // undefined → fällt im Konstruktor auf encode zurück
stream: cam.stream !== false, // UI "Aus" → Kamera startet nicht live
onDemand: ON_DEMAND, idleGraceMs: IDLE_GRACE_MS,
});
camsMeta.push({
@@ -57,11 +67,18 @@ for (const cam of camsConfig) {
}
const app = express();
app.use(express.json()); // POST /api/config liest JSON-Body
// ── 1. Eigene Endpunkte ───────────────────────────────────────────────────────
app.use('/api/snapshot', createSnapshotRouter(switches, camsMeta));
app.use('/api/stream', createStreamRouter(switches));
app.use('/api/cameras', createCamerasRouter(camsMeta));
app.use('/api/config', createConfigRouter({
switches, camsMeta,
getCamerasJson: () => camerasJson,
setCamerasJson: (v) => { camerasJson = v; },
persist: persistCameras,
}));
app.get('/health', (_req, res) => {
res.json({