"use client"; // components/modules/Kue705FO.tsx import React, { useState, useEffect, useRef } from "react"; import ReactModal from "react-modal"; import Chart from "chart.js/auto"; import { useSelector } from "react-redux"; import KueModal from "../modales/kueModal/KueModal"; import "bootstrap-icons/font/bootstrap-icons.css"; // Import Bootstrap Icons import { RootState } from "../../store/store"; interface DataTDR { t: number; // Oder Date, falls t ein Datum ist m: number; // Der Wert für den Pegel } const Kue705FO: React.FC = ({ isolationswert, schleifenwiderstand, modulName, kueOnline, slotIndex, tdrLocation, alarmStatus, }) => { /* console.log( `Rendering Kue705FO - SlotIndex: ${slotIndex}, ModulName: ${modulName}` ); */ const chartRef = useRef(null); const [zoomPlugin, setZoomPlugin] = useState(null); // Plugin-Status für Chart.js const [kueVersion, setKueVersion] = useState("V4.19"); const [currentAlarmStatus, setCurrentAlarmStatus] = useState(false); const [currentModulName, setCurrentModulName] = useState(modulName); const [activeButton, setActiveButton] = useState("Schleife"); const [loopTitleText, setloopTitleText] = useState( "Schleifenwiderstand [kOhm]" ); const [loopDisplayValue, setLoopDisplayValue] = useState(schleifenwiderstand); // Initialisiere den loopDisplayValue mit schleifenwiderstand const [isoDisplayText, setIsoDisplayText] = useState("Aderbruch"); const [groundFaultDisplayText, setGroundFaultDisplayText] = useState("Erdschluss"); const [loopFaultDisplayText, setLoopFaultDisplayText] = useState("Schleifenfehler"); const [isoFaultDisplayText, setIsoFaultDisplayText] = useState("Isolationsfehler"); const [isoGreaterThan200, setIsoGreaterThan200] = useState(">200 MOhm"); const [loading, setLoading] = useState(false); const [isoDisplayValue, setIsoDisplayValue] = useState< string | JSX.Element >(); //Test erstmal leer ohne isolationswert const [showModal, setShowModal] = useState(false); const [showChartModal, setShowChartModal] = useState(false); const [chartData, setChartData] = useState(null); // Redux-Variablen abrufen const { kuePSTmMinus96V, kueCableBreak, kueGroundFault, kueAlarm1, kueAlarm2, kueOverflow, kueVersion: reduxKueVersion, tdrActive, } = useSelector((state: RootState) => state.variables); const handleOpenModal = () => setShowModal(true); const handleCloseModal = () => setShowModal(false); const handleOpenChartModal = () => { setShowChartModal(true); if (activeButton === "TDR") { loadTDRChartData(); } else { loadLoopChartData(); } }; const handleButtonClick = (button: "Schleife" | "TDR") => { if (button === "Schleife") { setActiveButton("Schleife"); setloopTitleText("Schleifenwiderstand [kOhm]"); setLoopDisplayValue(schleifenwiderstand); // Setze den Wert auf schleifenwiderstand } else if (button === "TDR") { setActiveButton("TDR"); setloopTitleText("Entfernung [Km]"); setLoopDisplayValue( tdrLocation && tdrLocation[slotIndex] !== undefined ? tdrLocation[slotIndex] : "0" ); // Setze den Wert auf tdrLocation oder "0" als Fallback } }; // Funktion für die Schleifenmessung const goLoop = () => { let slot: number = slotIndex; if (slot >= 32) { return; } // Entfernt führende Nullen, falls vorhanden let slotFormat = slot < 10 ? `${slot}` : `${slot}`; setLoading(true); // Setze den Ladezustand auf true alert(`Schleifenmessung wird für Slot ${slot + 1} gestartet...`); fetch(`/CPL?kabelueberwachung.html&KS_${slotFormat}=1&slot=${slot}`, { method: "GET", }) .then((response) => { if (response.ok) { alert(`Schleifenmessung erfolgreich gestartet für Slot ${slot + 1}`); console.log("Schleifenmessung erfolgreich gestartet für Slot", slot); } else { alert("Fehler beim Starten der Schleifenmessung."); console.error("Fehler beim Senden der Schleifen-Anfrage"); } }) .catch((error) => { alert("Ein Fehler ist aufgetreten."); console.error("Fehler:", error); }) .finally(() => setLoading(false)); // Ladezustand zurücksetzen }; // Funktion für die TDR-Messung const goTDR = () => { //------------------------------------------------- let slot: number = slotIndex; if (slot >= 32) { return; } // Entfernt führende Nullen, falls vorhanden let slotFormat = slot < 10 ? `${slot}` : `${slot}`; setLoading(true); alert(`TDR wird für Slot ${slot + 1} gestartet...`); fetch( `/CPL?Service/Kabelueberwachung.html&KTT${slotFormat}=1&slot=${slot}`, { method: "GET", } ) .then((response) => { if (response.ok) { alert(`TDR erfolgreich gestartet für Slot ${slot + 1}`); console.log("TDR erfolgreich gestartet für Slot", slot + 1); } else { console.error("Fehler beim Senden der TDR-Anfrage"); } }) .catch((error) => { console.error("Fehler:", error); }) .finally(() => setLoading(false)); }; // Bestimme, welche Funktion ausgeführt wird, basierend auf dem aktiven Button const handleRefreshClick = () => { if (activeButton === "Schleife") { goLoop(); // Wenn Schleife aktiv ist, starte goLoop } else if (activeButton === "TDR") { goTDR(); // Wenn TDR aktiv ist, starte goTDR } }; const handleCloseChartModal = () => setShowChartModal(false); // Funktion zum Erstellen des TDR-Charts const createTDRChart = (dataTDR: DataTDR[]) => { const canvas = document.getElementById("myChart") as HTMLCanvasElement; const ctx = canvas?.getContext("2d"); if (!ctx) { console.error("Canvas context konnte nicht gefunden werden"); return; } new Chart(ctx, { type: "line", data: { labels: dataTDR.map((row) => row.t), datasets: [ { label: "Pegel", data: dataTDR.map((row) => row.m), borderColor: "#00AEEF", borderWidth: 1, pointBorderWidth: 0, pointStyle: false, fill: false, yAxisID: "y", }, ], }, options: { scales: { x: { type: "linear", position: "left", title: { display: true, text: "Meter" }, }, }, plugins: { zoom: { pan: { enabled: true, mode: "xy", }, zoom: { wheel: { enabled: true, // Zoom mit Mausrad }, pinch: { enabled: true, // Pinch-Zoom für Touchgeräte }, mode: "xy", // x und y Achsen zoomen }, }, }, }, }); }; const loadTDRChartData = () => { const slot = slotIndex; const environment = process.env.NODE_ENV || "production"; const fileData = environment === "production" ? `/CPL?/CPL/lastTDR/slot${slot}.json` : `/CPLmockData/lastTDR/slot${slot}.json`; fetch(fileData) .then((response) => response.json()) .then((data) => { setChartData(data); createTDRChart(data); }) .catch((error) => console.error("Fehler beim Laden der TDR-Messkurvendaten:", error) ); }; const loadLoopChartData = () => { const slot = slotIndex; const environment = process.env.NODE_ENV || "production"; const fileData = environment === "production" ? `/CPL?/CPL/4000values/slot${slot}.json` : `/CPLmockData/4000values/slot${slot}.json`; fetch(fileData) .then((response) => response.json()) .then((data) => { setChartData(data); createLoopChart(data, "Schleifenmesskurve"); }) .catch((error) => console.error("Fehler beim Laden der Schleifenmesskurvendaten:", error) ); }; // Füge das Plugin zu Chart.js hinzu useEffect(() => { // Lade das Plugin nur, wenn `window` verfügbar ist if (typeof window !== "undefined") { import("chartjs-plugin-zoom").then((mod) => { setZoomPlugin(mod.default); // Setze das Plugin Chart.register(mod.default); // Plugin zur Chart.js-Instanz registrieren }); } }, []); interface DataLoop { t: number; // Zeit oder Index m: number; // Isolationswiderstand n: number; // Schleifenwiderstand } const createLoopChart = (data: DataLoop[], title: string) => { const canvas = document.getElementById("myChart") as HTMLCanvasElement; if (!canvas) { console.error("Canvas mit ID 'myChart' nicht gefunden."); return; } const ctx = canvas.getContext("2d"); if (!ctx) { console.error("2D-Kontext für Canvas konnte nicht erstellt werden."); return; } // Konvertiere Zeitstempel in ein lesbares Format für die X-Achse const labels = data.map((row) => { const date = new Date(String(row.t).replace(/-/g, "/")); // Zeitstring parsen return date.toLocaleString("de-DE", { hour: "2-digit", minute: "2-digit", second: "2-digit", }); }); new Chart(ctx, { type: "line", data: { labels, datasets: [ { label: "Isolationswiderstand (MOhm)", data: data.map((row) => row.m), borderColor: "#00AEEF", borderWidth: 1, tension: 0.1, // Glättung der Linie pointRadius: 1, pointHoverRadius: 5, fill: false, yAxisID: "y", }, { label: "Schleifenwiderstand (kOhm)", data: data.map((row) => row.n), borderColor: "black", borderWidth: 1, tension: 0.1, pointRadius: 1, pointHoverRadius: 5, fill: false, yAxisID: "y1", }, ], }, options: { scales: { x: { type: "category", title: { display: true, text: "Zeit" }, }, y: { type: "linear", position: "left", title: { display: true, text: "MOhm" }, }, y1: { type: "linear", position: "right", title: { display: true, text: "kOhm" }, }, }, plugins: { zoom: { pan: { enabled: true, mode: "xy", }, zoom: { wheel: { enabled: true, }, pinch: { enabled: true, }, mode: "xy", }, }, }, }, }); }; useEffect(() => { const updateAlarmStatus = () => { const alarmStatus = (kueAlarm1 && kueAlarm1[slotIndex]) || (kueAlarm2 && kueAlarm2[slotIndex]) || (kueCableBreak && kueCableBreak[slotIndex]) || (kueGroundFault && kueGroundFault[slotIndex]); setCurrentAlarmStatus(!!alarmStatus); // Wandelt string oder undefined in boolean um }; updateAlarmStatus(); const interval = setInterval(updateAlarmStatus, 10000); return () => clearInterval(interval); }, [slotIndex, kueAlarm1, kueAlarm2, kueCableBreak, kueGroundFault]); useEffect(() => { if (reduxKueVersion?.[slotIndex]) { setKueVersion("V" + reduxKueVersion[slotIndex] / 100); } }, [slotIndex, reduxKueVersion]); //--------------------------------------------------- // Funktion zum Aktualisieren der Anzeige basierend auf dem Alarmstatus mit Icon und Blinken // Funktion zum Aktualisieren der Anzeige basierend auf dem Alarmstatus mit Icon und Blinken useEffect(() => { let intervalId: NodeJS.Timeout | undefined; // Funktion zum Blinken des Textes oder Icons const setBlinkingText = (text: string | JSX.Element) => { // Setze den Text direkt beim ersten Aufruf, ohne auf das Intervall zu warten setIsoDisplayValue(text); // Starte dann das Intervall intervalId = setInterval(() => { setIsoDisplayValue((prevValue) => prevValue === text ? ( ) : ( text ) ); }, 5000); // Intervall für das Blinken }; // Priorisierte Alarmanzeige if (Number(kuePSTmMinus96V?.[slotIndex]) === 1) { clearInterval(intervalId); // Stoppt das vorherige Intervall, falls aktiv setBlinkingText("PST-M prüfen"); } else if (Number(kueCableBreak?.[slotIndex]) === 1) { clearInterval(intervalId); setBlinkingText(isoDisplayText); } else if (Number(kueGroundFault?.[slotIndex]) === 1) { clearInterval(intervalId); setBlinkingText(groundFaultDisplayText); } else if (Number(kueAlarm1?.[slotIndex]) === 1) { clearInterval(intervalId); setBlinkingText(isoFaultDisplayText); } else if (Number(kueAlarm2?.[slotIndex]) === 1) { clearInterval(intervalId); setBlinkingText(loopFaultDisplayText); } else if (Number(kueOverflow?.[slotIndex]) === 1) { clearInterval(intervalId); setIsoDisplayValue(isoGreaterThan200); } else { clearInterval(intervalId); setIsoDisplayValue(isolationswert.toString()); // Standardanzeige ohne Alarm } // Cleanup bei Änderungen des Status oder Schließen des Effekts return () => clearInterval(intervalId); }, [ slotIndex, isolationswert, isoDisplayText, groundFaultDisplayText, isoFaultDisplayText, loopFaultDisplayText, isoGreaterThan200, kuePSTmMinus96V, kueCableBreak, kueGroundFault, kueAlarm1, kueAlarm2, kueOverflow, ]); //--------------------------------------------------- // Effekt, um Modulnamen zu aktualisieren, wenn sich der Prop ändert useEffect(() => { setCurrentModulName(modulName); //console.log(`Modulname aktualisiert für Slot ${slotIndex}:`, modulName); }, [modulName, slotIndex]); //--------------------------------------------------- // Aktualisiert den Schleifenwiderstand, wenn sich der `schleifenwiderstand`-Prop ändert useEffect(() => { if (activeButton === "Schleife") { setLoopDisplayValue(schleifenwiderstand); } }, [schleifenwiderstand, activeButton]); //--------------------------------------------------- return (
{kueOnline === 1 ? ( <>
{slotIndex + 1}

KÜ705-FO

{}
Betrieb Alarm
{/* Anzeige des Isolation */}
{isoDisplayValue} {Number(kuePSTmMinus96V?.[slotIndex]) !== 1 && Number(kueCableBreak?.[slotIndex]) !== 1 && Number(kueGroundFault?.[slotIndex]) !== 1 && Number(kueAlarm1?.[slotIndex]) !== 1 && Number(kueAlarm2?.[slotIndex]) !== 1 && Number(kueOverflow?.[slotIndex]) !== 1 && (
ISO MOhm
)}
{currentModulName || `Modul ${slotIndex + 1}`}
{kueVersion}
{/* loopDisplay: Zeigt Schleifenwiderstand oder TDR-Distanz an, je nach Modus */}
{loopTitleText}

{loopDisplayValue + (activeButton === "Schleife" ? " KOhm" : " Km")}

{/* Modal für Messkurve */} {showChartModal && (

Messkurve Slot {slotIndex + 1}

)} ) : (

Kein Modul im Slot {slotIndex + 1}

)}
); }; export default Kue705FO; interface Kue705FOProps { isolationswert: number | string | JSX.Element; schleifenwiderstand: number | string; modulName: string; kueOnline: number; slotIndex: number; tdrLocation: number[]; alarmStatus?: boolean; }