Files
CPLv4.0/mocks/scripts/fetchCableData.mjs
ISA 71f120aa27 fetchCableData.mjs
Sends Authorization: Basic <base64(user:pass)> with configurable credentials.
Accepts --user and --pass, or env CPL_USER/CPL_PASS; defaults to Littwin/Littwin.
Uses an https.Agent({ rejectUnauthorized: false }) when --insecure is set.
Corrected output folder to cable-monitoring-data.
CLI parser supports both --key=value and --key value (PowerShell friendly).
Quick usage (PowerShell)

All 32 slots, both types (iso=3, rsl=4), all DIA modes, last 30 days:
npm run mocks:cable
Specific date range (e.g., 2025-07-13 to 2025-08-12), all slots and types:
node .\mocks\scripts\fetchCableData.mjs --from 2025-07-13 --to 2025-08-12 --insecure
Only slot 0, Isolationswiderstand, DIA1:
node .\mocks\scripts\fetchCableData.mjs --slots 0 --modes DIA1 --types iso --from 2025-07-13 --to 2025-08-12 --insecure
Provide credentials explicitly:
node .\mocks\scripts\fetchCableData.mjs --user Littwin --pass Littwin --insecure
Or via environment variables for the session:
$env:CPL_USER = "Littwin"; $env:CPL_PASS = "Littwin"
node .\mocks\scripts\fetchCableData.mjs --insecure
Output structure

mocks/device-cgi-simulator/cable-monitoring-data/slot{0..31}/
isolationswiderstand/DIA0.json, DIA1.json, DIA2.json
schleifenwiderstand/DIA0.json, DIA1.json, DIA2.json
I smoke-tested slot 0, DIA1, iso with login and it produced DIA1.json under slot0/isolationswiderstand. If you need me to also add a convenience npm script with user/pass placeholders, say the credentials source you prefer (env vs args), and I’ll wire it.
2025-08-12 10:50:08 +02:00

214 lines
6.2 KiB
JavaScript

#!/usr/bin/env node
// Fetch and update cable monitoring mock data for 32 slots (0-31)
// Writes to mocks/device-cgi-simulator/cable-monitoring-data/slot{N}/{isolationswiderstand|schleifenwiderstand}/DIA{0|1|2}.json
// Usage examples (PowerShell):
// node mocks/scripts/fetchCableData.mjs --base https://10.10.0.118 --from 2025-07-13 --to 2025-08-12 --insecure
// node mocks/scripts/fetchCableData.mjs --slots 0-3 --modes DIA0,DIA1 --types iso --insecure
import fs from "node:fs/promises";
import path from "node:path";
import https from "node:https";
// Simple CLI args parser supporting "--key=value" and "--key value"
const args = (() => {
const out = {};
const argv = process.argv.slice(2);
for (let i = 0; i < argv.length; i++) {
const tok = argv[i];
if (tok.startsWith("--")) {
const eq = tok.indexOf("=");
if (eq !== -1) {
const key = tok.slice(2, eq);
const val = tok.slice(eq + 1);
out[key] = val;
} else {
const key = tok.slice(2);
const next = argv[i + 1];
if (next && !next.startsWith("--")) {
out[key] = next;
i++;
} else {
out[key] = true;
}
}
}
}
return out;
})();
const BASE_URL =
args.base || process.env.CPL_DEVICE_BASE_URL || "https://10.10.0.118";
const MODES = String(args.modes || "DIA0,DIA1,DIA2")
.split(",")
.map((s) => s.trim())
.filter(Boolean);
const TYPES = String(args.types || "iso,rsl")
.split(",")
.map((s) => s.trim())
.filter(Boolean); // iso -> 3, rsl -> 4
const SLOTS = (() => {
if (args.slots) {
if (String(args.slots).includes("-")) {
const [a, b] = String(args.slots).split("-").map(Number);
return Array.from({ length: b - a + 1 }, (_, i) => a + i);
}
return String(args.slots)
.split(",")
.map((s) => Number(s.trim()));
}
return Array.from({ length: 32 }, (_, i) => i);
})();
const today = new Date();
const defaultFrom = new Date(today);
defaultFrom.setDate(today.getDate() - 30);
const fromISO =
args.from ||
process.env.CPL_FROM_DATE ||
defaultFrom.toISOString().slice(0, 10); // YYYY-MM-DD
const toISO =
args.to || process.env.CPL_TO_DATE || today.toISOString().slice(0, 10);
const OUT_DIR =
args.out ||
path.join(
process.cwd(),
"mocks",
"device-cgi-simulator",
"cable-monitoring-data"
);
const INSECURE = Boolean(args.insecure || process.env.CPL_INSECURE);
if (INSECURE) {
// Allow self-signed certs for local device
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
}
// Basic Auth credentials (same default as fetchSystemData.mjs)
const USERNAME = args.user || process.env.CPL_USER || "Littwin";
const PASSWORD = args.pass || process.env.CPL_PASS || "Littwin";
const AUTH_HEADER =
"Basic " + Buffer.from(`${USERNAME}:${PASSWORD}`).toString("base64");
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const toACPDate = (iso) => {
const [y, m, d] = iso.split("-");
return `${y};${m};${d}`;
};
const typeToFolderAndCode = (typeKey) => {
switch (typeKey) {
case "iso":
return { folder: "isolationswiderstand", code: 3 };
case "rsl":
case "schleife":
return { folder: "schleifenwiderstand", code: 4 };
default:
throw new Error(`Unknown type '${typeKey}'. Use iso or rsl.`);
}
};
const buildUrl = (mode, from, to, slot, typeCode) =>
`${BASE_URL}/CPL?seite.ACP&${mode}=${toACPDate(from)};${toACPDate(
to
)};${slot};${typeCode};`;
async function fetchJson(url) {
// Prefer node-fetch when INSECURE to pass https.Agent; otherwise use global fetch when available
let doFetch = globalThis.fetch;
if (INSECURE || typeof doFetch === "undefined") {
const { default: nf } = await import("node-fetch");
doFetch = nf;
}
const init = { headers: { Authorization: AUTH_HEADER } };
if (INSECURE) {
init.agent = new https.Agent({ rejectUnauthorized: false });
}
const res = await doFetch(url, init);
if (!res.ok) {
const text = await res.text().catch(() => "");
throw new Error(`HTTP ${res.status} ${res.statusText} for ${url}\n${text}`);
}
return res.json();
}
async function ensureDir(dir) {
await fs.mkdir(dir, { recursive: true });
}
async function writeJson(file, data) {
await ensureDir(path.dirname(file));
await fs.writeFile(file, JSON.stringify(data, null, 2), "utf8");
}
async function main() {
console.log(`➡️ Fetch cable data`);
console.log(` Base: ${BASE_URL}`);
console.log(` Range: ${fromISO}${toISO}`);
console.log(` Slots: ${SLOTS.join(",")}`);
console.log(` Modes: ${MODES.join(",")}`);
console.log(` Types: ${TYPES.join(",")}`);
console.log(` Out: ${OUT_DIR}`);
if (INSECURE) console.log(` TLS: insecure (self-signed allowed)`);
// Small concurrency to avoid hammering the device
const MAX_CONCURRENCY = Number(args.concurrency || 3);
let running = 0;
let idx = 0;
const tasks = [];
for (const slot of SLOTS) {
for (const typeKey of TYPES) {
const { folder, code } = typeToFolderAndCode(typeKey);
for (const mode of MODES) {
tasks.push({ slot, typeKey, folder, code, mode });
}
}
}
const runNext = async () => {
if (idx >= tasks.length) return;
const task = tasks[idx++];
running++;
try {
const url = buildUrl(task.mode, fromISO, toISO, task.slot, task.code);
console.log(`→ [slot ${task.slot}] ${task.folder} ${task.mode}`);
const data = await fetchJson(url);
const file = path.join(
OUT_DIR,
`slot${task.slot}`,
task.folder,
`${task.mode}.json`
);
await writeJson(file, data);
} catch (e) {
console.error(
`✖ Fehler bei slot ${task.slot} ${task.folder} ${task.mode}:`,
e.message || e
);
} finally {
running--;
// polite delay between requests
await sleep(Number(args.delay || 150));
if (idx < tasks.length) runNext();
}
};
// Start initial workers
const starters = Math.min(MAX_CONCURRENCY, tasks.length);
for (let i = 0; i < starters; i++) runNext();
// Wait for all to finish
while (running > 0 || idx < tasks.length) {
await sleep(100);
}
console.log("✅ Fertig.");
}
main().catch((e) => {
console.error("Unerwarteter Fehler:", e);
process.exit(1);
});