feat: digitalOutputs separate jsSimulatedProd mode

This commit is contained in:
Ismail Ali
2025-06-22 09:46:13 +02:00
parent 041bc3e23e
commit ff3f418636
9 changed files with 44 additions and 26 deletions

View File

@@ -6,5 +6,5 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
NEXT_PUBLIC_EXPORT_STATIC=false NEXT_PUBLIC_EXPORT_STATIC=false
NEXT_PUBLIC_USE_CGI=false NEXT_PUBLIC_USE_CGI=false
# App-Versionsnummer # App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.442 NEXT_PUBLIC_APP_VERSION=1.6.443
NEXT_PUBLIC_CPL_MODE=jsSimulatedProd # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter) NEXT_PUBLIC_CPL_MODE=jsSimulatedProd # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)

View File

@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
NEXT_PUBLIC_EXPORT_STATIC=true NEXT_PUBLIC_EXPORT_STATIC=true
NEXT_PUBLIC_USE_CGI=true NEXT_PUBLIC_USE_CGI=true
# App-Versionsnummer # App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.442 NEXT_PUBLIC_APP_VERSION=1.6.443
NEXT_PUBLIC_CPL_MODE=production NEXT_PUBLIC_CPL_MODE=production

View File

@@ -1,3 +1,15 @@
## [1.6.443] 2025-06-22
- feat: jsSimulatedProd-Modus für analoge & digitale Eingänge implementiert
- neuen Modus `jsSimulatedProd` eingeführt für realitätsnahe Simulation auf Basis echter Produktionsdaten
- analoge Eingänge: analogInputsMockData.js eingebunden und dynamisch per Script geladen
- digitale Eingänge: digitalInputsMockData.js eingebunden mit window-Variablen (z.B. win_de_state, win_de_label etc.)
- fetchAnalogInputsService.ts und fetchDigitalInputsService.ts angepasst zur Modusprüfung und Script-Auswertung
- getAnalogInputsHandler.ts und getDigitalInputsHandler.ts geben im jsSimulatedProd-Modus JavaScript-Dateien aus
- .env.development setzt `NEXT_PUBLIC_CPL_MODE=jsSimulatedProd`
---
## [1.6.442] 2025-06-22 ## [1.6.442] 2025-06-22
- docs: add full architecture diagram and data flow for json, jsmock and production modes - docs: add full architecture diagram and data flow for json, jsmock and production modes

View File

@@ -1,2 +1,2 @@
win_da_state = [1, 1, 1, 1]; win_da_state = [1, 1, 1, 1];
win_da_bezeichnung = ["Ausgang1", "Ausgang2", "Ausgang3", "Ausgang4"]; win_da_bezeichnung = ["Ausgang2", "Ausgang2", "Ausgang3", "Ausgang4"];

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.442", "version": "1.6.443",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.442", "version": "1.6.443",
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.1.0", "@fontsource/roboto": "^5.1.0",
"@iconify-icons/ri": "^1.2.10", "@iconify-icons/ri": "^1.2.10",

View File

@@ -1,6 +1,6 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.442", "version": "1.6.443",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",

View File

@@ -21,12 +21,12 @@ export default function handler(req: NextApiRequest, res: NextApiResponse) {
} }
if (mode === "jsSimulatedProd") { if (mode === "jsSimulatedProd") {
const analogInputsScript = fs.readFileSync( const digitalInputsScript = fs.readFileSync(
"mocks/device-cgi-simulator/SERVICE/digitalInputsMockData.js", "mocks/device-cgi-simulator/SERVICE/digitalInputsMockData.js",
"utf-8" "utf-8"
); );
res.setHeader("Content-Type", "application/javascript"); res.setHeader("Content-Type", "application/javascript");
res.status(200).send(analogInputsScript); res.status(200).send(digitalInputsScript);
return; return;
} }

View File

@@ -3,6 +3,7 @@
import { NextApiRequest, NextApiResponse } from "next"; import { NextApiRequest, NextApiResponse } from "next";
import path from "path"; import path from "path";
import fs from "fs/promises"; import fs from "fs/promises";
import { readFileSync } from "fs";
export default async function handler( export default async function handler(
req: NextApiRequest, req: NextApiRequest,
@@ -22,25 +23,12 @@ export default async function handler(
} }
if (mode === "jsSimulatedProd") { if (mode === "jsSimulatedProd") {
// Lese Datei und extrahiere window-Variablen aus .js-Datei const digitalOutputsScript = readFileSync(
const filePath = path.join(
process.cwd(),
"mocks/device-cgi-simulator/SERVICE/digitalOutputsMockData.js" "mocks/device-cgi-simulator/SERVICE/digitalOutputsMockData.js"
); );
const fileContent = await fs.readFile(filePath, "utf-8"); res.setHeader("Content-Type", "application/javascript");
res.status(200).send(digitalOutputsScript);
const stateMatch = fileContent.match(/win_da_state\s*=\s*\[([^\]]*)\]/); return;
const labelMatch = fileContent.match(
/win_da_bezeichnung\s*=\s*\[([^\]]*)\]/
);
const win_da_state =
stateMatch?.[1]?.split(",").map((x) => parseInt(x.trim())) || [];
const win_da_bezeichnung =
labelMatch?.[1]?.split(",").map((x) => x.trim().replace(/["']/g, "")) ||
[];
return res.status(200).json({ win_da_state, win_da_bezeichnung });
} }
return res.status(400).json({ error: "Unsupported mode" }); return res.status(400).json({ error: "Unsupported mode" });

View File

@@ -33,7 +33,7 @@ export const fetchDigitalOutputsService = async () => {
status: status === 1, status: status === 1,
})); }));
} }
} else if (mode === "json" || mode === "jsSimulatedProd") { } else if (mode === "json") {
const res = await fetch("/api/cpl/getDigitalOutputsHandler"); const res = await fetch("/api/cpl/getDigitalOutputsHandler");
if (!res.ok) { if (!res.ok) {
@@ -57,6 +57,24 @@ export const fetchDigitalOutputsService = async () => {
})); }));
} }
} }
} else if (mode === "jsSimulatedProd") {
console.log("🔄 Lade simulierte analoge Eingänge im Produktionsmodus...");
const scriptUrl = "/api/cpl/getDigitalOutputsHandler"; // gibt JavaScript zurück
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 win = window as any;
return Array.from({ length: 4 }, (_, i) => ({
id: i + 1,
label: win.win_da_bezeichnung[i] || `Ausgang ${i + 1}`,
status: win.win_da_state[i] === 1,
}));
} else { } else {
console.warn(`⚠️ Unbekannter Modus: ${mode}`); console.warn(`⚠️ Unbekannter Modus: ${mode}`);
return []; return [];