feat:
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:
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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 className="text-[0.55rem] block">
|
</span>
|
||||||
{isoDisplayValue} MOhm
|
{/* 2. Zeile: ISO-Wert, immer anzeigen */}
|
||||||
</span>
|
<span
|
||||||
</div>
|
className={`whitespace-nowrap block text-[0.65rem] font-semibold ${
|
||||||
) : Number(kueAlarm2?.[slotIndex]) === 1 ? (
|
Number(kueAlarm1?.[slotIndex]) === 1 ? "text-red-500" : ""
|
||||||
"Schleifenfehler"
|
}`}
|
||||||
) : (
|
>
|
||||||
<>
|
{isoDisplayValue === "Abgleich"
|
||||||
<span className="block text-[0.7rem] font-semibold">
|
? "ISO: Abgleich"
|
||||||
<span className="block text-[0.6rem] text-gray-300">
|
: `ISO: ${Number(isolationswert)} MOhm`}
|
||||||
ISO: {" "}
|
</span>
|
||||||
{isoDisplayValue} MOhm
|
{/* 3. Zeile: Schleifenwert, in Rot bei Schleifenfehler, sonst normal */}
|
||||||
</span>
|
<span
|
||||||
</span>
|
className={`whitespace-nowrap block text-[0.65rem] font-semibold ${
|
||||||
</>
|
Number(kueAlarm2?.[slotIndex]) === 1 ? "text-red-500" : ""
|
||||||
)}
|
}`}
|
||||||
|
>
|
||||||
|
{activeButton === "Schleife" && loading
|
||||||
|
? "RSL: Messung"
|
||||||
|
: `RSL: ${loopDisplayValue} kOhm`}
|
||||||
</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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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={{
|
||||||
|
|||||||
16
docs/TODO.md
16
docs/TODO.md
@@ -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
|
||||||
|
|||||||
@@ -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
4
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user