Anzeige KÜ-Display:

1. Zeile Alarm: Isolationsfehler, Schleifenfehler, Aderbruch, Erdschluß, Messpannung: Immer in Rot; wenn kein Alarm, bleibt die Zeile leer

2. Zeile: Isowert: xx MOhm (großes M)

in Rot, wenn Iso-Fehler ansteht

Beispiel: ISO: 100 MOHm der beim Abliech:  ISO: Abgleich

3. Zeile: Schleifenwert, xx kOhm (kleines k)

in Rot, wenn Schleifenfehler ansteht

Beispiel:: RSL: 1,7 kOhm oder wenn Schleifenmessung aktiv: RSL: Messung
This commit is contained in:
ISA
2025-07-24 13:59:44 +02:00
parent c1f6c19fdf
commit e932bee120
10 changed files with 117 additions and 67 deletions

View File

@@ -6,6 +6,6 @@ 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.644 NEXT_PUBLIC_APP_VERSION=1.6.645
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter) NEXT_PUBLIC_CPL_MODE=json # 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.644 NEXT_PUBLIC_APP_VERSION=1.6.645
NEXT_PUBLIC_CPL_MODE=production NEXT_PUBLIC_CPL_MODE=production

View File

@@ -1,3 +1,8 @@
## [1.6.645] 2025-07-24
- Feat: Fenster nicht schließen für Firmware Update
---
## [1.6.644] 2025-07-24 ## [1.6.644] 2025-07-24
- Firmware Update Bestätigung in Littwin blau - Firmware Update Bestätigung in Littwin blau

View File

@@ -220,67 +220,53 @@ const Kue705FO: React.FC<Kue705FOProps> = ({
</div> </div>
</div> </div>
{/* Anzeige des Isolation und Schleifenwiderstand zusammen */} {/* Schwarzes Display mit drei Zeilen: Alarm, ISO, Schleife */}
<div className="relative mt-[3.125rem] mx-auto bg-black text-white w-[6.25rem] h-[3.1rem] flex flex-col items-center justify-center z-10 p-1"> <div className="relative mt-[3.125rem] mx-auto bg-black text-white w-[6.8rem] h-[3.1rem] flex flex-col items-center justify-center z-10 p-1">
<div className="text-center w-full"> <div className="text-center w-full flex flex-col justify-center items-center h-full">
{/* 1. Zeile: Alarmtext in Rot, sonst leer */}
<span <span
className={ className={`whitespace-nowrap block text-[0.65rem] font-semibold ${
Number(kuePSTmMinus96V?.[slotIndex]) === 1 || Number(kuePSTmMinus96V?.[slotIndex]) === 1 ||
Number(kueCableBreak?.[slotIndex]) === 1 || Number(kueCableBreak?.[slotIndex]) === 1 ||
Number(kueGroundFault?.[slotIndex]) === 1 || Number(kueGroundFault?.[slotIndex]) === 1 ||
Number(kueAlarm1?.[slotIndex]) === 1 || Number(kueAlarm1?.[slotIndex]) === 1 ||
Number(kueAlarm2?.[slotIndex]) === 1 Number(kueAlarm2?.[slotIndex]) === 1
? "text-red-500 text-[0.65rem]" ? "text-red-500"
: Number(kueOverflow?.[slotIndex]) === 1
? "text-white text-[0.65rem]"
: "" : ""
} }`}
> >
{Number(kuePSTmMinus96V?.[slotIndex]) === 1 ? ( {Number(kuePSTmMinus96V?.[slotIndex]) === 1
"PST Fehler" ? "Messpannung"
) : Number(kueCableBreak?.[slotIndex]) === 1 ? ( : Number(kueCableBreak?.[slotIndex]) === 1
"Aderbruch" ? "Aderbruch"
) : Number(kueGroundFault?.[slotIndex]) === 1 ? ( : Number(kueGroundFault?.[slotIndex]) === 1
"Erdschluss" ? "Erdschluss"
) : Number(kueAlarm1?.[slotIndex]) === 1 ? ( : Number(kueAlarm1?.[slotIndex]) === 1
<div> ? "Isolationsfehler"
<span className="text-[0.55rem] block"> : Number(kueAlarm2?.[slotIndex]) === 1
Isolationsfehler ? "Schleifenfehler"
: ""}
</span> </span>
<span className="text-[0.55rem] block"> {/* 2. Zeile: ISO-Wert, immer anzeigen */}
{isoDisplayValue} MOhm <span
className={`whitespace-nowrap block text-[0.65rem] font-semibold ${
Number(kueAlarm1?.[slotIndex]) === 1 ? "text-red-500" : ""
}`}
>
{isoDisplayValue === "Abgleich"
? "ISO: Abgleich"
: `ISO: ${Number(isolationswert)} MOhm`}
</span> </span>
</div> {/* 3. Zeile: Schleifenwert, in Rot bei Schleifenfehler, sonst normal */}
) : Number(kueAlarm2?.[slotIndex]) === 1 ? ( <span
"Schleifenfehler" className={`whitespace-nowrap block text-[0.65rem] font-semibold ${
) : ( Number(kueAlarm2?.[slotIndex]) === 1 ? "text-red-500" : ""
<> }`}
<span className="block text-[0.7rem] font-semibold"> >
<span className="block text-[0.6rem] text-gray-300"> {activeButton === "Schleife" && loading
ISO: {" "} ? "RSL: Messung"
{isoDisplayValue} MOhm : `RSL: ${loopDisplayValue} kOhm`}
</span> </span>
</span>
</>
)}
</span>
{/* Schleifenwiderstand immer anzeigen, außer bei Fehlern */}
{![
Number(kuePSTmMinus96V?.[slotIndex]),
Number(kueCableBreak?.[slotIndex]),
Number(kueGroundFault?.[slotIndex]),
Number(kueAlarm1?.[slotIndex]),
Number(kueAlarm2?.[slotIndex]),
].includes(1) && (
<>
<span className="block text-[0.7rem] mt-1 font-semibold">
<span className="block text-[0.6rem] text-gray-300">
Sch.: {" "}
{loopDisplayValue} kOhm
</span>
</span>
</>
)}
</div> </div>
</div> </div>

View File

@@ -126,6 +126,7 @@ export const DetailModal = ({
const [chartData, setChartData] = useState<any>({ const [chartData, setChartData] = useState<any>({
datasets: [], datasets: [],
}); });
const [isLoading, setIsLoading] = useState(false);
const vonDatum = useSelector( const vonDatum = useSelector(
(state: RootState) => state.kabelueberwachungChartSlice.vonDatum (state: RootState) => state.kabelueberwachungChartSlice.vonDatum
); );
@@ -186,6 +187,7 @@ export const DetailModal = ({
}, []); }, []);
const handleFetchData = () => { const handleFetchData = () => {
setIsLoading(true);
let sortedData = [...reduxData].reverse(); let sortedData = [...reduxData].reverse();
if (vonDatum && bisDatum) { if (vonDatum && bisDatum) {
@@ -254,10 +256,31 @@ export const DetailModal = ({
} }
}, [isOpen, selectedKey]); }, [isOpen, selectedKey]);
// Chart.js animation complete callback to set isLoading false
useEffect(() => {
if (chartRef.current && isLoading) {
const chartInstance = chartRef.current;
// Save previous callback to restore later
const prevCallback = chartInstance.options.animation?.onComplete;
chartInstance.options.animation = {
...chartInstance.options.animation,
onComplete: () => {
setIsLoading(false);
if (typeof prevCallback === "function") prevCallback();
},
};
chartInstance.update();
}
}, [chartData, isLoading]);
if (!isOpen || !selectedKey) return null; if (!isOpen || !selectedKey) return null;
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50"> <div
className={`fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50 ${
isLoading ? "cursor-wait" : ""
}`}
>
<div <div
className={`bg-white p-6 rounded-xl overflow-auto shadow-2xl transition-all duration-300 ${ className={`bg-white p-6 rounded-xl overflow-auto shadow-2xl transition-all duration-300 ${
isFullScreen ? "w-[95vw] h-[90vh]" : "w-[50%] h-[60%]" isFullScreen ? "w-[95vw] h-[90vh]" : "w-[50%] h-[60%]"
@@ -347,9 +370,12 @@ export const DetailModal = ({
</Listbox> </Listbox>
<button <button
onClick={handleFetchData} onClick={handleFetchData}
className="px-4 py-1 bg-littwin-blue text-white rounded text-sm" className={`px-4 py-1 bg-littwin-blue text-white rounded text-sm ${
isLoading ? "cursor-wait" : ""
}`}
disabled={isLoading}
> >
Daten laden {isLoading ? "Laden..." : "Daten laden"}
</button> </button>
</div> </div>

View File

@@ -38,6 +38,7 @@ type Props = {
zeitraum: "DIA0" | "DIA1" | "DIA2"; zeitraum: "DIA0" | "DIA1" | "DIA2";
}; };
export const SystemCharts = ({ history }: Props) => { export const SystemCharts = ({ history }: Props) => {
const [isLoading, setIsLoading] = React.useState(true);
const reversedHistory = [...history].reverse(); const reversedHistory = [...history].reverse();
const labels = reversedHistory.map((h) => const labels = reversedHistory.map((h) =>
new Date(h.time).toLocaleTimeString() new Date(h.time).toLocaleTimeString()
@@ -45,9 +46,21 @@ export const SystemCharts = ({ history }: Props) => {
const formatValue = (v: number) => v.toFixed(2); const formatValue = (v: number) => v.toFixed(2);
// Chart.js animation callback
const animation = {
onComplete: () => {
setIsLoading(false);
},
};
React.useEffect(() => {
setIsLoading(true);
}, [history]);
const baseOptions = { const baseOptions = {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
animation,
scales: { scales: {
y: { y: {
beginAtZero: false, beginAtZero: false,
@@ -65,7 +78,11 @@ export const SystemCharts = ({ history }: Props) => {
}; };
return ( return (
<div className="grid grid-cols-1 xl:grid-cols-2 gap-8"> <div
className={`grid grid-cols-1 xl:grid-cols-2 gap-8 ${
isLoading ? "cursor-wait" : ""
}`}
>
<div className="h-[300px]"> <div className="h-[300px]">
<Line <Line
data={{ data={{

View File

@@ -41,3 +41,19 @@
- [x] TODO: KÜ Firmware in progress Bitte Fenster nicht schließen - [x] TODO: KÜ Firmware in progress Bitte Fenster nicht schließen
- [ ] TODO: KÜ Kurve und letzte historische Meldungen anzeigen -> später - [ ] TODO: KÜ Kurve und letzte historische Meldungen anzeigen -> später
- [ ] TODO: KVz später - [ ] TODO: KVz später
Anzeige KÜ-Display:
1. Zeile Alarm: Isolationsfehler, Schleifenfehler, Aderbruch, Erdschluß, Messpannung: Immer in Rot; wenn kein Alarm, bleibt die Zeile leer
2. Zeile: Isowert: xx MOhm (großes M)
in Rot, wenn Iso-Fehler ansteht
Beispiel: ISO: 100 MOHm der beim Abliech: ISO: Abgleich
3. Zeile: Schleifenwert, xx kOhm (kleines k)
in Rot, wenn Schleifenfehler ansteht
Beispiel:: RSL: 1,7 kOhm oder wenn Schleifenmessung aktiv: RSL: Messung

View File

@@ -15,8 +15,8 @@ var win_kuePSTmMinus96V = [
]; ];
//Aderbruch 1 = Fehler, 0 = kein Fehler //Aderbruch 1 = Fehler, 0 = kein Fehler
var win_kueCableBreak = [ var win_kueCableBreak = [
1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0,
]; ];
//Erdschluss 1 = Fehler, 0 = kein Fehler //Erdschluss 1 = Fehler, 0 = kein Fehler
var win_kueGroundFault = [ var win_kueGroundFault = [
@@ -25,12 +25,12 @@ var win_kueGroundFault = [
]; ];
//Isolationsfehler 1 = Fehler, 0 = kein Fehler, Alarm kommt wenn kueIso < kueLimit1 //Isolationsfehler 1 = Fehler, 0 = kein Fehler, Alarm kommt wenn kueIso < kueLimit1
var win_kueAlarm1 = [ var win_kueAlarm1 = [
1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];
//Schleifenfehler 1 = Fehler, 0 = kein Fehler //Schleifenfehler 1 = Fehler, 0 = kein Fehler
var win_kueAlarm2 = [ var win_kueAlarm2 = [
1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]; ];
//Überlauf 1 = Fehler, 0 = kein Fehler , hier wird in Display ">200 MOhm" angezeigt //Überlauf 1 = Fehler, 0 = kein Fehler , hier wird in Display ">200 MOhm" angezeigt
@@ -62,9 +62,9 @@ die Filterzeit startet beim nächsten Unterschreiten des Grenzwerts neu. Die Fil
kurzfristige Schwankungen oder Störungen fälschlicherweise als Fehler gemeldet werden. kurzfristige Schwankungen oder Störungen fälschlicherweise als Fehler gemeldet werden.
*/ */
var win_kueDelay1 = [ var win_kueDelay1 = [
3, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420,
420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420,
420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, 420,
420, 420,
]; ];
//--------------------------------------------------- //---------------------------------------------------
//Schleifenwiderstand in Display (resDisplay) Einheit: KOhm //Schleifenwiderstand in Display (resDisplay) Einheit: KOhm

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.644", "version": "1.6.645",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.644", "version": "1.6.645",
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.1.0", "@fontsource/roboto": "^5.1.0",
"@headlessui/react": "^2.2.4", "@headlessui/react": "^2.2.4",

View File

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