feat: CGI-kompatiblen CSV-Parser für digitale Eingänge implementiert
- digitaleInputsMockData.json angepasst: CGI-nahe Simulation mit CSV-Strings und Stringwerten - fetchDigitalInputsService.ts erweitert: - CSV-Zeilen werden automatisch in Arrays umgewandelt - Labels wie "'DE1','DE2'" werden korrekt aufgeteilt - Daten aus 4 CGI-Blöcken zu 32 Eingängen gemappt - ermöglicht realitätsnahe Tests in Entwicklungsumgebung ohne Produktion
This commit is contained in:
@@ -1,109 +1,95 @@
|
||||
// ✅ Service: /services/fetchDigitalInputsService.ts
|
||||
export interface DigitalInput {
|
||||
id: number;
|
||||
value: number | string;
|
||||
label: string;
|
||||
invert: boolean;
|
||||
counter: number | string;
|
||||
timeFilter: number | string;
|
||||
weighting: number | string;
|
||||
counterActive: boolean;
|
||||
eingangOffline: boolean;
|
||||
status: boolean;
|
||||
flutter: boolean;
|
||||
zaehlerAktiv: boolean;
|
||||
}
|
||||
|
||||
export const fetchDigitalInputsService = async () => {
|
||||
const mode = process.env.NEXT_PUBLIC_CPL_MODE;
|
||||
// 🧠 Neu: CSV-Zeile wie "1,0,1,0" in [1,0,1,0] konvertieren
|
||||
const parseCsvNumbers = (line: string): number[] =>
|
||||
line.split(",").map((v) => Number(v.trim()));
|
||||
|
||||
// ✅ PRODUKTIV: lädt JavaScript vom Gerät über CGI
|
||||
if (mode === "production") {
|
||||
console.log("🔄 Lade analoge Eingänge im Produktionsmodus...");
|
||||
const scriptUrl = "/CPL?/CPL/SERVICE/digitalInputs.js";
|
||||
// 🧠 Neu: CSV-Zeile wie "'DE1','DE2'" in ["DE1", "DE2"] umwandeln
|
||||
const parseCsvLabels = (line: string): string[] =>
|
||||
line.split(",").map((v) => v.trim().replace(/^'+|'+$/g, ""));
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const script = document.createElement("script");
|
||||
script.src = scriptUrl;
|
||||
script.async = true;
|
||||
script.onload = () => resolve();
|
||||
script.onerror = () =>
|
||||
reject("❌ Fehler beim Laden der digitalen Eingänge (production)");
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
export const fetchDigitalInputsService = async (): Promise<DigitalInput[]> => {
|
||||
const mode = "production"; // ⛳ production oder json
|
||||
|
||||
const win = window as any;
|
||||
const url =
|
||||
mode === "production"
|
||||
? "/CPL?/CPL/SERVICE/digitalInputs.json"
|
||||
: "/api/cpl/getDigitalInputsHandler";
|
||||
|
||||
return Array.from({ length: 32 }, (_, i) => ({
|
||||
id: i + 1,
|
||||
value: win.win_de_state[i],
|
||||
label: win.win_de_label[i],
|
||||
invert: !!win.win_de_invert[i],
|
||||
counter: win.win_de_counter[i],
|
||||
timeFilter: win.win_de_time_filter[i],
|
||||
weighting: win.win_de_weighting[i],
|
||||
counterActive: !!win.win_de_counter_active[i],
|
||||
eingangOffline: !!win.win_de_offline[i],
|
||||
status: !!win.win_de_state[i],
|
||||
}));
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) {
|
||||
throw new Error(`❌ Fehler beim Laden der digitalen Eingänge (${mode})`);
|
||||
}
|
||||
|
||||
// ✅ JSON-MODUS (API gibt JSON-Daten zurück)
|
||||
else if (mode === "json") {
|
||||
console.log("🔄 Lade digitale Eingänge im JSON-Modus...");
|
||||
const res = await fetch("/api/cpl/getDigitalInputsHandler");
|
||||
if (!res.ok)
|
||||
throw new Error("❌ Fehler beim Laden der digitalen Eingänge (json)");
|
||||
const data = await res.json();
|
||||
|
||||
const data = await res.json();
|
||||
console.log("📡 JSON-Daten geladen in service:", data);
|
||||
return data.win_de_state.map((_: any, i: number) => ({
|
||||
id: i + 1,
|
||||
value: data.win_de_state[i],
|
||||
label: data.win_de_label[i],
|
||||
invert: !!data.win_de_invert[i],
|
||||
counter: data.win_de_counter[i],
|
||||
timeFilter: data.win_de_time_filter[i],
|
||||
weighting: data.win_de_weighting[i],
|
||||
counterActive: !!data.win_de_counter_active[i],
|
||||
eingangOffline: !!data.win_de_offline[i],
|
||||
status: !!data.win_de_state[i],
|
||||
}));
|
||||
// 🧠 Neu: CSV-Zeilen in Arrays umwandeln
|
||||
const state = data.win_de_state.flatMap(parseCsvNumbers);
|
||||
const label = data.win_de_label.flatMap(parseCsvLabels);
|
||||
const invert = data.win_de_invert.flatMap(parseCsvNumbers);
|
||||
const counter = data.win_de_counter.flatMap((line: string) =>
|
||||
line.split(",").map((v) => v.trim())
|
||||
);
|
||||
const timeFilter = data.win_de_time_filter.flatMap((line: string) =>
|
||||
line.split(",").map((v) => v.trim())
|
||||
);
|
||||
const weighting = data.win_de_weighting.flatMap((line: string) =>
|
||||
line.split(",").map((v) => v.trim())
|
||||
);
|
||||
const counterActive = data.win_de_counter_active.flatMap(parseCsvNumbers);
|
||||
const offline = data.win_de_offline.flatMap(parseCsvNumbers);
|
||||
|
||||
interface CsvData {
|
||||
state: number[];
|
||||
label: string[];
|
||||
invert: number[];
|
||||
counter: (number | string)[];
|
||||
timeFilter: (number | string)[];
|
||||
weighting: (number | string)[];
|
||||
counterActive: number[];
|
||||
offline: number[];
|
||||
}
|
||||
|
||||
// ✅ jsSimulatedProd-MODUS (Script einbinden und aus window lesen)
|
||||
else if (mode === "jsSimulatedProd") {
|
||||
console.log("🔄 Lade digitale Eingänge im jsSimulatedProd-Modus...");
|
||||
// const res = await fetch("/api/cpl/getDigitalInputsHandler");
|
||||
//------------------------
|
||||
const scriptUrl = "/api/cpl/getDigitalInputsHandler"; // gibt JavaScript zurück
|
||||
// Removed redundant DigitalInputResult interface
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const script = document.createElement("script");
|
||||
script.src = scriptUrl;
|
||||
script.async = true;
|
||||
script.onload = () => resolve();
|
||||
script.onerror = () =>
|
||||
reject("❌ Fehler beim Laden des simulierten Scripts");
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
const csvData: CsvData = {
|
||||
state,
|
||||
label,
|
||||
invert,
|
||||
counter,
|
||||
timeFilter,
|
||||
weighting,
|
||||
counterActive,
|
||||
offline,
|
||||
};
|
||||
|
||||
// Annahme: Das Script setzt window.win_de_state usw.
|
||||
const data = {
|
||||
win_de_state: (window as any).win_de_state,
|
||||
win_de_label: (window as any).win_de_label,
|
||||
win_de_invert: (window as any).win_de_invert,
|
||||
win_de_counter: (window as any).win_de_counter,
|
||||
win_de_time_filter: (window as any).win_de_time_filter,
|
||||
win_de_weighting: (window as any).win_de_weighting,
|
||||
win_de_counter_active: (window as any).win_de_counter_active,
|
||||
win_de_offline: (window as any).win_de_offline,
|
||||
};
|
||||
|
||||
//--------------------------
|
||||
|
||||
console.log("📡 jsSimulatedProd-Daten geladen in service:", data);
|
||||
|
||||
return data.win_de_state.map((_: any, i: number) => ({
|
||||
return csvData.state.map(
|
||||
(_, i): DigitalInput => ({
|
||||
id: i + 1,
|
||||
value: data.win_de_state[i],
|
||||
label: data.win_de_label[i],
|
||||
invert: !!data.win_de_invert[i],
|
||||
counter: data.win_de_counter[i],
|
||||
timeFilter: data.win_de_time_filter[i],
|
||||
weighting: data.win_de_weighting[i],
|
||||
counterActive: !!data.win_de_counter_active[i],
|
||||
eingangOffline: !!data.win_de_offline[i],
|
||||
status: !!data.win_de_state[i],
|
||||
}));
|
||||
}
|
||||
|
||||
// ❌ Unbekannter Modus
|
||||
throw new Error(`❌ Unbekannter NEXT_PUBLIC_CPL_MODE: ${mode}`);
|
||||
value: csvData.state[i],
|
||||
label: csvData.label[i],
|
||||
invert: !!csvData.invert[i],
|
||||
counter: csvData.counter[i],
|
||||
timeFilter: csvData.timeFilter[i],
|
||||
weighting: csvData.weighting[i],
|
||||
counterActive: !!csvData.counterActive[i],
|
||||
eingangOffline: !!csvData.offline[i],
|
||||
status: !!csvData.state[i],
|
||||
flutter: false,
|
||||
zaehlerAktiv: false,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user