Files
CPLv4.0/utils/loadWindowVariables.ts
Ismail Ali 65cfb033a5 feat: Digitale Ausgänge aus Redux-Store in UI integriert
- DigitalOutputs.tsx auf Redux umgestellt, um Werte direkt aus dem Store zu lesen
- toggleSwitch-Funktion angepasst, um den Status von digitalen Ausgängen in Redux zu aktualisieren
- useDigitalOutputsData.ts nutzt nun Redux zum Speichern der `win_da_state` und `win_da_bezeichnung` Werte
- Entfernen von Prop `digitalOutputs` in `DigitalOutputs.tsx`, da Redux nun als Datenquelle dient
- Weboberfläche zeigt nun digitale Ausgänge korrekt an und Status kann geändert werden
2025-02-23 22:31:06 +01:00

267 lines
7.9 KiB
TypeScript

// /utils/loadWindowVariables.ts
import store from "../redux/store";
import { setSystemSettings } from "../redux/slices/systemSettingsSlice";
import {
toggleOpcUaServer,
setOpcUaEncryption,
setOpcUaZustand,
setOpcUaActiveClientCount,
setOpcUaNodesetName,
addOpcUaUser,
removeOpcUaUser,
} from "../redux/slices/opcuaSettingsSlice";
import { setDigitalOutputs } from "../redux/slices/digitalOutputsSlice";
// ✅ Interface für `window`-Objekt zur TypeScript-Sicherheit
interface CustomWindow extends Window {
[key: string]: any;
}
// ✅ Interface für System-Einstellungen im Redux-Store
interface SystemSettings {
deviceName: string;
mac1: string;
ip: string;
subnet: string;
gateway: string;
cplInternalTimestamp: string;
ntp1: string;
ntp2: string;
ntp3: string;
ntpTimezone: string;
ntpActive: boolean;
}
// ✅ Interface für OPC-UA Einstellungen im Redux-Store
interface OpcUaSettings {
isEnabled: boolean;
encryption: string;
opcUaZustand: string;
opcUaActiveClientCount: number;
opcUaNodesetName: string;
users: { id: number; username: string; password: string }[];
}
// ✅ Hauptfunktion zum Laden von `window`-Variablen
export async function loadWindowVariables(): Promise<Record<string, any>> {
return new Promise((resolve, reject) => {
const requiredVars: string[] = [
"win_last20Messages",
"win_deviceName",
"win_mac1",
"win_ip",
"win_subnet",
"win_gateway",
"win_cplInternalTimestamp",
"win_ntp1",
"win_ntp2",
"win_ntp3",
"win_systemZeit",
"win_ntpTimezone",
"win_ntpActive",
"win_de_state",
"win_counter",
"win_flutter",
"win_kueOnline",
"win_kueID",
"win_kuePSTmMinus96V",
"win_kueAlarm1",
"win_kueAlarm2",
"win_kueIso",
"win_kueResidence",
"win_kueCableBreak",
"win_kueGroundFault",
"win_kueLimit1",
"win_kueLimit2Low",
"win_kueDelay1",
"win_kueLoopInterval",
"win_kueVersion",
"win_tdrAtten",
"win_tdrPulse",
"win_tdrSpeed",
"win_tdrAmp",
"win_tdrTrigger",
"win_tdrLocation",
"win_tdrActive",
"win_kueOverflow",
"win_tdrLast",
"win_appVersion",
"win_analogeEingaenge1",
"win_analogeEingaenge2",
"win_analogeEingaenge3",
"win_analogeEingaenge4",
"win_analogeEingaenge5",
"win_analogeEingaenge6",
"win_analogeEingaenge7",
"win_analogeEingaenge8",
"win_da_state",
"win_da_bezeichnung",
"win_opcUaZustand",
"win_opcUaActiveClientCount",
"win_opcUaNodesetName",
"win_opcUaEncryption", // ✅ NEU: Verschlüsselung von OPC-UA
"win_opcUaUsers", // ✅ NEU: OPC-UA Benutzerliste
];
const scripts: string[] = [
"da.js",
"de.js",
"ae.js",
"kueData.js",
"Start.js",
"System.js",
"opcua.js",
];
const loadScript = (src: string): Promise<void> => {
return new Promise((resolve, reject) => {
const script = document.createElement("script");
const environment = process.env.NEXT_PUBLIC_NODE_ENV || "production";
script.src =
environment === "production"
? `/CPL?/CPL/SERVICE/${src}`
: `/CPLmockData/SERVICE/${src}`;
script.async = true;
script.onload = () => resolve();
script.onerror = () => reject(new Error(`Script load error: ${src}`));
document.head.appendChild(script);
});
};
// ✅ Lade alle Skripte nacheinander
scripts
.reduce(
(promise, script) => promise.then(() => loadScript(script)),
Promise.resolve()
)
.then(() => {
const win = window as unknown as CustomWindow;
// ✅ Erstelle ein Objekt mit allen geladenen Variablen
const variablesObj: Record<string, any> = requiredVars.reduce(
(acc, variable) => {
if (win[variable] !== undefined) {
acc[variable.replace("win_", "")] = win[variable];
}
return acc;
},
{}
);
// ✅ Redux mit Systemvariablen aktualisieren
loadAndStoreSystemSettings(win);
loadAndStoreOpcUaSettings(win);
resolve(variablesObj);
})
.catch((error) => {
console.error("Fehler beim Laden eines Skripts:", error);
reject(error);
});
});
}
// ✅ Funktion zum Speichern von System-Variablen in Redux
const loadAndStoreSystemSettings = (win: CustomWindow) => {
const settings: SystemSettings = {
deviceName: win.win_deviceName || "",
mac1: win.win_mac1 || "",
ip: win.win_ip || "",
subnet: win.win_subnet || "",
gateway: win.win_gateway || "",
cplInternalTimestamp: win.win_cplInternalTimestamp || "",
ntp1: win.win_ntp1 || "",
ntp2: win.win_ntp2 || "",
ntp3: win.win_ntp3 || "",
ntpTimezone: win.win_ntpTimezone || "",
ntpActive: win.win_ntpActive || false,
};
store.dispatch(setSystemSettings(settings));
};
// ✅ Funktion zum Speichern von OPC-UA Variablen in Redux
const loadAndStoreOpcUaSettings = (win: CustomWindow) => {
// ✅ Aktuellen Redux-Status holen
const currentState = store.getState().opcuaSettings;
// ✅ Nur setzen, wenn sich der Zustand geändert hat
if (currentState.opcUaZustand !== win.win_opcUaZustand) {
store.dispatch(setOpcUaZustand(win.win_opcUaZustand || "Offline"));
}
// ✅ Nur setzen, wenn sich die Verschlüsselung geändert hat
if (currentState.encryption !== win.win_opcUaEncryption) {
store.dispatch(setOpcUaEncryption(win.win_opcUaEncryption || "None"));
}
// ✅ Nur setzen, wenn sich die Anzahl der aktiven Clients geändert hat
if (currentState.opcUaActiveClientCount !== win.win_opcUaActiveClientCount) {
store.dispatch(
setOpcUaActiveClientCount(win.win_opcUaActiveClientCount || 0)
);
}
// ✅ Nur setzen, wenn sich der Nodeset-Name geändert hat
if (currentState.opcUaNodesetName !== win.win_opcUaNodesetName) {
store.dispatch(
setOpcUaNodesetName(win.win_opcUaNodesetName || "DefaultNodeset")
);
}
// ✅ Benutzer synchronisieren (aber nicht überschreiben, wenn manuell hinzugefügt)
if (Array.isArray(win.win_opcUaUsers) && win.win_opcUaUsers.length > 0) {
const newUsers = win.win_opcUaUsers;
const currentUsers = currentState.users;
// ✅ Vorhandene Benutzer entfernen, die nicht mehr in `window` sind
currentUsers.forEach((user) => {
if (!newUsers.some((newUser) => newUser.username === user.username)) {
store.dispatch(removeOpcUaUser(user.id));
}
});
// ✅ Nur neue Benutzer hinzufügen, falls sie nicht existieren
newUsers.forEach((user) => {
if (
!currentUsers.some(
(existingUser) => existingUser.username === user.username
)
) {
store.dispatch(
addOpcUaUser({ username: user.username, password: user.password })
);
}
});
}
};
// ✅ Funktion zum Speichern der digitalen Ausgänge in Redux
const loadAndStoreDigitalOutputs = (win: CustomWindow) => {
console.log("Prüfe digitale Ausgänge in window:");
console.log("win_da_state:", win.win_da_state);
console.log("win_da_bezeichnung:", win.win_da_bezeichnung);
if (
Array.isArray(win.win_da_state) &&
Array.isArray(win.win_da_bezeichnung) &&
win.win_da_state.length === win.win_da_bezeichnung.length
) {
const digitalOutputs = win.win_da_state.map(
(status: number, index: number) => ({
id: index + 1,
label: win.win_da_bezeichnung[index] || `Ausgang ${index + 1}`,
status: status === 1, // Status in Boolean umwandeln
})
);
console.log("Dispatching digitalOutputs:", digitalOutputs);
store.dispatch(setDigitalOutputs(digitalOutputs));
} else {
console.warn("Digitale Ausgänge konnten nicht geladen werden:", {
da_state: win.win_da_state,
da_bezeichnung: win.win_da_bezeichnung,
});
}
};