Compare commits

8 Commits

Author SHA1 Message Date
ISA
859a8f1d64 feat: fetch-Services für Spannung und Temperatur für Dev- und Prod-Modus angepasst
- fetchSystemspannung5VplusService: Channel 110 (+5V), prod = /cpl?/dashboard.html
- fetchSystemspannung15VplusService: Channel 108 (+15V)
- fetchSystemspannung15VminusService: Channel 114 (-15V)
- fetchSystemspannung98VminusService: Channel 115 (-98V)
- fetchTemperaturAdWandlerService: Channel 116 (Temperatur AD-Wandler)
- fetchTemperaturProzessorService: Channel 117 (Temperatur Prozessor)

→ Dev-Mode verwendet API-Handler (/api/cpl/...)
→ Production-Mode nutzt CGI-kompatible URLs (/cpl?/dashboard.html&...)

Fehlerbehandlung integriert, Struktur für Wiederverwendung vereinheitlicht
2025-07-03 14:02:16 +02:00
ISA
b1eb3c46a8 feat: Detailansicht auf dynamische Redux-Datenquellen umgestellt
- DetailModal.tsx überarbeitet, um Redux-Daten je nach ausgewähltem Key (+5V, +15V, -15V, -98V, ADC Temp, CPU Temp) anzuzeigen
- Zeitraum-Auswahl (DIA0, DIA1, DIA2) wird berücksichtigt und löst passenden Thunk aus
- Redux-State-Struktur vollständig integriert für Systemspannungen und Temperaturen
- Chart-Anzeige jetzt dynamisch und erweiterbar
2025-07-03 12:24:53 +02:00
ISA
a0e8e47fae feat: APIs erstellt für Systemspannungen 2025-07-03 11:48:52 +02:00
ISA
521bd7ea93 feat: in System 5 Volt DIA0, DIA1 und DIA2 in dropdown anzeigen 2025-07-03 11:14:18 +02:00
ISA
3e7d702ab7 feat: in System 5 Volt DIA0, DIA1 und DIA2 in dropdown anzeigen 2025-07-03 11:13:39 +02:00
ISA
09bc64e771 feat: API für Systemspannung +5V erfolgreich implementiert
- API-Handler `getSystemspannung5VplusHandler.ts` erstellt
- JSON-Daten werden aus dem Verzeichnis `mocks/device-cgi-simulator/chartsData/systemspannung5Vplus/` geladen
- unterstützt die Parameter DIA0, DIA1, DIA2 für unterschiedliche Datenfrequenzen
- Fehlerbehandlung bei ungültigen Typen und fehlenden Dateien eingebaut
- API getestet unter `/api/cpl/getSystemspannung5VplusHandler?typ=DIA0`
2025-07-03 10:23:39 +02:00
ISA
cee3ee0581 feat: API für Systemspannung +5V erfolgreich implementiert
- API-Handler `getSystemspannung5VplusHandler.ts` erstellt
- JSON-Daten werden aus dem Verzeichnis `mocks/device-cgi-simulator/chartsData/systemspannung5Vplus/` geladen
- unterstützt die Parameter DIA0, DIA1, DIA2 für unterschiedliche Datenfrequenzen
- Fehlerbehandlung bei ungültigen Typen und fehlenden Dateien eingebaut
- API getestet unter `/api/cpl/getSystemspannung5VplusHandler?typ=DIA0`
2025-07-03 10:23:04 +02:00
ISA
4245d7a991 fix: KÜ Firmwareupdate 2025-07-03 07:36:10 +02:00
39 changed files with 1250 additions and 176 deletions

View File

@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
NEXT_PUBLIC_EXPORT_STATIC=false
NEXT_PUBLIC_USE_CGI=false
# App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.526
NEXT_PUBLIC_APP_VERSION=1.6.538
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_USE_CGI=true
# App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.526
NEXT_PUBLIC_APP_VERSION=1.6.538
NEXT_PUBLIC_CPL_MODE=production

View File

@@ -1,3 +1,91 @@
## [1.6.538] 2025-07-03
- feat: Detailansicht auf dynamische Redux-Datenquellen umgestellt
- DetailModal.tsx überarbeitet, um Redux-Daten je nach ausgewähltem Key (+5V, +15V, -15V, -98V, ADC Temp, CPU Temp) anzuzeigen
- Zeitraum-Auswahl (DIA0, DIA1, DIA2) wird berücksichtigt und löst passenden Thunk aus
- Redux-State-Struktur vollständig integriert für Systemspannungen und Temperaturen
- Chart-Anzeige jetzt dynamisch und erweiterbar
---
## [1.6.537] 2025-07-03
- feat: APIs erstellt für Systemspannungen
---
## [1.6.536] 2025-07-03
- feat: APIs erstellt für Systemspannungen
---
## [1.6.535] 2025-07-03
- feat: in System 5 Volt DIA0, DIA1 und DIA2 in dropdown anzeigen
---
## [1.6.534] 2025-07-03
- feat: in System 5 Volt DIA0, DIA1 und DIA2 in dropdown anzeigen
---
## [1.6.533] 2025-07-03
- feat: API für Systemspannung +5V erfolgreich implementiert
- API-Handler `getSystemspannung5VplusHandler.ts` erstellt
- JSON-Daten werden aus dem Verzeichnis `mocks/device-cgi-simulator/chartsData/systemspannung5Vplus/` geladen
- unterstützt die Parameter DIA0, DIA1, DIA2 für unterschiedliche Datenfrequenzen
- Fehlerbehandlung bei ungültigen Typen und fehlenden Dateien eingebaut
- API getestet unter `/api/cpl/getSystemspannung5VplusHandler?typ=DIA0`
---
## [1.6.532] 2025-07-03
- feat: API für Systemspannung +5V erfolgreich implementiert
- API-Handler `getSystemspannung5VplusHandler.ts` erstellt
- JSON-Daten werden aus dem Verzeichnis `mocks/device-cgi-simulator/chartsData/systemspannung5Vplus/` geladen
- unterstützt die Parameter DIA0, DIA1, DIA2 für unterschiedliche Datenfrequenzen
- Fehlerbehandlung bei ungültigen Typen und fehlenden Dateien eingebaut
- API getestet unter `/api/cpl/getSystemspannung5VplusHandler?typ=DIA0`
---
## [1.6.531] 2025-07-03
- feat: API für Systemspannung +5V erfolgreich implementiert
- API-Handler `getSystemspannung5VplusHandler.ts` erstellt
- JSON-Daten werden aus dem Verzeichnis `mocks/device-cgi-simulator/chartsData/systemspannung5Vplus/` geladen
- unterstützt die Parameter DIA0, DIA1, DIA2 für unterschiedliche Datenfrequenzen
- Fehlerbehandlung bei ungültigen Typen und fehlenden Dateien eingebaut
- API getestet unter `/api/cpl/getSystemspannung5VplusHandler?typ=DIA0`
---
## [1.6.530] 2025-07-03
- fix: KÜ Firmwareupdate
---
## [1.6.529] 2025-07-03
- fix: KÜ Firmwareupdate
---
## [1.6.528] 2025-07-03
- fix: KÜ Firmwareupdate
---
## [1.6.527] 2025-07-03
- fix: Firmware-Update läuft nun exakt 5 Minuten bis 100% Fortschritt
- Fehler behoben, bei dem das Firmware-Update nach wenigen Sekunden vorzeitig beendet wurde
- Fortschrittsanzeige über Redux-Slice `firmwareProgressSlice` korrekt umgesetzt
- Thunk `startFirmwareUpdateThunk` korrekt eingebunden und verwendet
- UI zeigt stabile 5-minütige Progressbar wie erwartet
---
## [1.6.526] 2025-07-02
- fix: Firmware-Update läuft nun exakt 5 Minuten bis 100% Fortschritt

View File

@@ -283,7 +283,11 @@ export default function KueEinstellung({
/>
)}
{isUpdating && (
<ProgressModal visible={isUpdating} progress={progress} />
<ProgressModal
visible={isUpdating}
progress={progress}
slot={slot + 1}
/>
)}
<button
onClick={() => handleDisplayEinschalten(slot)}

View File

@@ -1,18 +1,29 @@
"use client";
// @/components/main/settingsPageComponents/modals/ProgressModal.tsx
import React from "react";
type Props = {
visible: boolean;
progress: number;
slot?: number;
};
const ProgressModal: React.FC<Props> = ({ visible, progress }) => {
const ProgressModal: React.FC<Props> = ({ visible, progress, slot }) => {
if (!visible) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 ">
<div className="bg-white p-6 rounded shadow-md text-center w-80">
<h2 className="text-lg font-bold mb-4">Firmwareupdate läuft...</h2>
{/*
<h2 className="text-lg font-bold mb-4">
Firmwareupdate
{typeof slot === "number" ? ` KÜ ${slot}` : ""} läuft ...
</h2>
*/}
<h2 className="text-lg font-bold mb-4">
Firmwareupdate läuft ...
{typeof slot === "number" ? ` ` : ""}
</h2>
<div className="w-full bg-gray-200 rounded-full h-4">
<div
className="bg-blue-500 h-4 rounded-full transition-all duration-100"

View File

@@ -0,0 +1,116 @@
// components/main/system/DetailModal.tsx
"use client";
import React from "react";
import { Line } from "react-chartjs-2";
import { useSelector } from "react-redux";
import { RootState } from "@/redux/store";
type Props = {
isOpen: boolean;
selectedKey: string | null;
onClose: () => void;
zeitraum: "DIA0" | "DIA1" | "DIA2";
setZeitraum: (typ: "DIA0" | "DIA1" | "DIA2") => void;
};
type ReduxDataEntry = { t: string; i: number };
export const DetailModal = ({
isOpen,
selectedKey,
onClose,
zeitraum,
setZeitraum,
}: Props) => {
const reduxData: ReduxDataEntry[] = useSelector((state: RootState) => {
switch (selectedKey) {
case "+5V":
return state.systemspannung5Vplus[zeitraum] as ReduxDataEntry[];
case "+15V":
return state.systemspannung15Vplus[zeitraum] as ReduxDataEntry[];
case "-15V":
return state.systemspannung15Vminus[zeitraum] as ReduxDataEntry[];
case "-98V":
return state.systemspannung98Vminus[zeitraum] as ReduxDataEntry[];
case "ADC Temp":
return state.temperaturAdWandler[zeitraum] as ReduxDataEntry[];
case "CPU Temp":
return state.temperaturProzessor[zeitraum] as ReduxDataEntry[];
default:
return [] as ReduxDataEntry[];
}
});
const labels = reduxData.map((e: ReduxDataEntry) => e.t);
const values = reduxData.map((e: ReduxDataEntry) => e.i);
const baseOptions = {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: false,
grid: { color: "rgba(200,200,200,0.2)" },
title: { display: true, text: "Wert" },
},
x: {
grid: { color: "rgba(200,200,200,0.2)" },
title: { display: true, text: "Zeit" },
},
},
plugins: {
legend: { position: "bottom" as const },
title: { display: true, text: `Verlauf ${selectedKey}` },
},
};
if (!isOpen || !selectedKey) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50">
<div className="bg-white p-6 rounded-xl w-[50%] h-[60%] overflow-auto shadow-2xl">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-semibold">
Detailansicht: {selectedKey}
</h2>
<button onClick={onClose} className="text-red-500 hover:text-red-700">
</button>
</div>
<div className="mb-4">
<label className="mr-2 font-medium">Zeitraum:</label>
<select
className="border px-2 py-1 rounded"
value={zeitraum}
onChange={(e) =>
setZeitraum(e.target.value as "DIA0" | "DIA1" | "DIA2")
}
>
<option value="DIA0">Alle Messwerte</option>
<option value="DIA1">Stündlich</option>
<option value="DIA2">Täglich</option>
</select>
</div>
<div className="h-[85%]">
<Line
data={{
labels,
datasets: [
{
label: selectedKey,
data: values,
borderColor: "rgba(59,130,246,1)",
backgroundColor: "rgba(59,130,246,0.2)",
fill: false,
},
],
}}
options={baseOptions}
/>
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,144 @@
// components/main/system/SystemCharts.tsx
import React from "react";
import { Line } from "react-chartjs-2";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from "chart.js";
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);
export type HistoryEntry = {
time: string | number | Date;
"+5V": number;
"+15V": number;
"-15V": number;
"-98V": number;
"ADC Temp": number;
"CPU Temp": number;
};
type Props = {
history: HistoryEntry[];
zeitraum: "DIA0" | "DIA1" | "DIA2";
};
export const SystemCharts = ({ history }: Props) => {
const labels = history.map((h) => new Date(h.time).toLocaleTimeString());
const formatValue = (v: number) => v.toFixed(2);
const baseOptions = {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: false,
grid: { color: "rgba(200,200,200,0.2)" },
title: { display: true, text: "Wert" },
},
x: {
grid: { color: "rgba(200,200,200,0.2)" },
title: { display: true, text: "Zeit" },
},
},
plugins: {
legend: { position: "bottom" as const },
},
};
return (
<div className="grid grid-cols-1 xl:grid-cols-2 gap-8">
<div className="h-[300px]">
<Line
data={{
labels,
datasets: [
{
label: "+5V",
data: history.map((h) => formatValue(h["+5V"])),
borderColor: "rgba(59,130,246,1)",
backgroundColor: "rgba(59,130,246,0.5)",
fill: false,
},
{
label: "+15V",
data: history.map((h) => formatValue(h["+15V"])),
borderColor: "rgba(34,197,94,1)",
backgroundColor: "rgba(34,197,94,0.5)",
fill: false,
},
{
label: "-15V",
data: history.map((h) => formatValue(h["-15V"])),
borderColor: "rgba(239,68,68,1)",
backgroundColor: "rgba(239,68,68,0.5)",
fill: false,
},
{
label: "-98V",
data: history.map((h) => formatValue(h["-98V"])),
borderColor: "rgba(234,179,8,1)",
backgroundColor: "rgba(234,179,8,0.5)",
fill: false,
},
],
}}
options={{
...baseOptions,
plugins: {
...baseOptions.plugins,
title: { display: true, text: "Systemspannungen" },
},
}}
/>
</div>
<div className="h-[300px]">
<Line
data={{
labels,
datasets: [
{
label: "ADC Temp",
data: history.map((h) => h["ADC Temp"]),
borderColor: "rgba(168,85,247,1)",
backgroundColor: "rgba(168,85,247,0.5)",
fill: false,
},
{
label: "CPU Temp",
data: history.map((h) =>
parseFloat(formatValue(h["CPU Temp"]))
),
borderColor: "rgba(251,191,36,1)",
backgroundColor: "rgba(251,191,36,0.5)",
fill: false,
},
],
}}
options={{
...baseOptions,
plugins: {
...baseOptions.plugins,
title: { display: true, text: "Systemtemperaturen" },
},
}}
/>
</div>
</div>
);
};

View File

@@ -0,0 +1,33 @@
// components/main/system/SystemOverviewGrid.tsx
import React from "react";
type Props = {
voltages: Record<string, number>;
onOpenDetail: (key: string) => void;
};
export const SystemOverviewGrid = ({ voltages, onOpenDetail }: Props) => {
const formatValue = (value: number) => value.toFixed(2);
return (
<div className="grid grid-cols-2 gap-4 mb-8">
{Object.entries(voltages).map(([key, value]) => {
const unit = key.includes("Temp") ? "°C" : "V";
return (
<div key={key} className="p-4 border rounded shadow">
<h2 className="font-semibold">{key}</h2>
<p>
{formatValue(value)} {unit}
<button
onClick={() => onOpenDetail(key)}
className="ml-2 text-blue-600 hover:underline text-sm"
>
Details
</button>
</p>
</div>
);
})}
</div>
);
};

4
package-lock.json generated
View File

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

View File

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

View File

@@ -0,0 +1,33 @@
import { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs/promises";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { typ = "DIA0" } = req.query;
if (!["DIA0", "DIA1", "DIA2"].includes(typ as string)) {
return res
.status(400)
.json({ error: "Ungültiger Typ. Nur DIA0, DIA1 oder DIA2 erlaubt." });
}
try {
const filePath = path.join(
process.cwd(),
"mocks/device-cgi-simulator/chartsData/systemspannung15Vminus",
`${typ}.json`
);
const fileContent = await fs.readFile(filePath, "utf-8");
const json = JSON.parse(fileContent);
return res.status(200).json(json);
} catch (error) {
console.error("❌ Fehler beim Lesen der Datei:", error);
return res
.status(500)
.json({ error: "Datei konnte nicht gelesen werden." });
}
}

View File

@@ -0,0 +1,33 @@
import { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs/promises";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { typ = "DIA0" } = req.query;
if (!["DIA0", "DIA1", "DIA2"].includes(typ as string)) {
return res
.status(400)
.json({ error: "Ungültiger Typ. Nur DIA0, DIA1 oder DIA2 erlaubt." });
}
try {
const filePath = path.join(
process.cwd(),
"mocks/device-cgi-simulator/chartsData/systemspannung15Vplus",
`${typ}.json`
);
const fileContent = await fs.readFile(filePath, "utf-8");
const json = JSON.parse(fileContent);
return res.status(200).json(json);
} catch (error) {
console.error("❌ Fehler beim Lesen der Datei:", error);
return res
.status(500)
.json({ error: "Datei konnte nicht gelesen werden." });
}
}

View File

@@ -0,0 +1,35 @@
// @/pages/api/cpl/getSystemspannung5VplusHandler.ts
import { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs/promises";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { typ = "DIA1" } = req.query;
if (!["DIA0", "DIA1", "DIA2"].includes(typ as string)) {
return res
.status(400)
.json({ error: "Ungültiger Typ. Nur DIA0, DIA1 oder DIA2 erlaubt." });
}
try {
// Verwende __dirname um relativen Pfad zur API-Datei zu bestimmen
const filePath = path.join(
process.cwd(), // ← Root-Projektverzeichnis
"mocks/device-cgi-simulator/chartsData/systemspannung5Vplus",
`${typ}.json`
);
const fileContent = await fs.readFile(filePath, "utf-8");
const json = JSON.parse(fileContent);
return res.status(200).json(json);
} catch (error) {
console.error("❌ Fehler beim Lesen der Datei:", error);
return res
.status(500)
.json({ error: "Datei konnte nicht gelesen werden." });
}
}

View File

@@ -0,0 +1,33 @@
import { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs/promises";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { typ = "DIA0" } = req.query;
if (!["DIA0", "DIA1", "DIA2"].includes(typ as string)) {
return res
.status(400)
.json({ error: "Ungültiger Typ. Nur DIA0, DIA1 oder DIA2 erlaubt." });
}
try {
const filePath = path.join(
process.cwd(),
"mocks/device-cgi-simulator/chartsData/systemspannung98Vminus",
`${typ}.json`
);
const fileContent = await fs.readFile(filePath, "utf-8");
const json = JSON.parse(fileContent);
return res.status(200).json(json);
} catch (error) {
console.error("❌ Fehler beim Lesen der Datei:", error);
return res
.status(500)
.json({ error: "Datei konnte nicht gelesen werden." });
}
}

View File

@@ -0,0 +1,33 @@
import { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs/promises";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { typ = "DIA0" } = req.query;
if (!["DIA0", "DIA1", "DIA2"].includes(typ as string)) {
return res
.status(400)
.json({ error: "Ungültiger Typ. Nur DIA0, DIA1 oder DIA2 erlaubt." });
}
try {
const filePath = path.join(
process.cwd(),
"mocks/device-cgi-simulator/chartsData/temperatur-ad-wandler",
`${typ}.json`
);
const fileContent = await fs.readFile(filePath, "utf-8");
const json = JSON.parse(fileContent);
return res.status(200).json(json);
} catch (error) {
console.error("❌ Fehler beim Lesen der Datei:", error);
return res
.status(500)
.json({ error: "Datei konnte nicht gelesen werden." });
}
}

View File

@@ -0,0 +1,33 @@
import { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs/promises";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { typ = "DIA0" } = req.query;
if (!["DIA0", "DIA1", "DIA2"].includes(typ as string)) {
return res
.status(400)
.json({ error: "Ungültiger Typ. Nur DIA0, DIA1 oder DIA2 erlaubt." });
}
try {
const filePath = path.join(
process.cwd(),
"mocks/device-cgi-simulator/chartsData/temperatur-prozessor",
`${typ}.json`
);
const fileContent = await fs.readFile(filePath, "utf-8");
const json = JSON.parse(fileContent);
return res.status(200).json(json);
} catch (error) {
console.error("❌ Fehler beim Lesen der Datei:", error);
return res
.status(500)
.json({ error: "Datei konnte nicht gelesen werden." });
}
}

View File

@@ -1,140 +1,60 @@
"use client"; // /pages/system.tsx
import React, { useEffect } from "react";
// pages/system.tsx
"use client";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "../redux/store";
import { getSystemVoltTempThunk } from "../redux/thunks/getSystemVoltTempThunk";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
TooltipItem,
} from "chart.js";
import { Line } from "react-chartjs-2";
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);
import { SystemOverviewGrid } from "@/components/main/system/SystemOverviewGrid";
import { SystemCharts } from "@/components/main/system/SystemCharts";
import { DetailModal } from "@/components/main/system/DetailModal";
import type { HistoryEntry } from "@/components/main/system/SystemCharts";
import { getSystemspannung5VplusThunk } from "@/redux/thunks/getSystemspannung5VplusThunk";
import { getSystemspannung15VplusThunk } from "@/redux/thunks/getSystemspannung15VplusThunk";
import { getSystemspannung15VminusThunk } from "@/redux/thunks/getSystemspannung15VminusThunk";
import { getSystemspannung98VminusThunk } from "@/redux/thunks/getSystemspannung98VminusThunk";
import { getTemperaturAdWandlerThunk } from "@/redux/thunks/getTemperaturAdWandlerThunk";
import { getTemperaturProzessorThunk } from "@/redux/thunks/getTemperaturProzessorThunk";
const SystemPage = () => {
const dispatch = useDispatch<AppDispatch>();
const voltages = useSelector(
(state: RootState) => state.systemVoltTemp.voltages
);
const history = useSelector(
(state: RootState) => state.systemVoltTemp.history
);
) as HistoryEntry[];
const [selectedKey, setSelectedKey] = useState<string | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [zeitraum, setZeitraum] = useState<"DIA0" | "DIA1" | "DIA2">("DIA1");
useEffect(() => {
dispatch(getSystemVoltTempThunk());
const interval = setInterval(() => {
dispatch(getSystemVoltTempThunk());
}, 5000);
return () => clearInterval(interval);
}, [dispatch]);
const labels = history.map((h) => new Date(h.time).toLocaleTimeString());
useEffect(() => {
dispatch(getSystemspannung5VplusThunk(zeitraum));
dispatch(getSystemspannung15VplusThunk(zeitraum));
dispatch(getSystemspannung15VminusThunk(zeitraum));
dispatch(getSystemspannung98VminusThunk(zeitraum));
dispatch(getTemperaturAdWandlerThunk(zeitraum));
dispatch(getTemperaturProzessorThunk(zeitraum));
}, [dispatch, zeitraum]);
const formatValue = (value: number) => value.toFixed(2);
const handleOpenDetail = (key: string) => {
setSelectedKey(key);
setIsModalOpen(true);
};
const voltageDatasets = [
{
label: "+5V",
data: history.map((h) => formatValue(h["+5V"])),
borderColor: "rgba(59,130,246,1)",
backgroundColor: "rgba(59,130,246,0.5)",
fill: false,
},
{
label: "+15V",
data: history.map((h) => formatValue(h["+15V"])),
borderColor: "rgba(34,197,94,1)",
backgroundColor: "rgba(34,197,94,0.5)",
fill: false,
},
{
label: "-15V",
data: history.map((h) => formatValue(h["-15V"])),
borderColor: "rgba(239,68,68,1)",
backgroundColor: "rgba(239,68,68,0.5)",
fill: false,
},
{
label: "-98V",
data: history.map((h) => formatValue(h["-98V"])),
borderColor: "rgba(234,179,8,1)",
backgroundColor: "rgba(234,179,8,0.5)",
fill: false,
},
];
const temperatureDatasets = [
{
label: "ADC Temp",
data: history.map((h) => h["ADC Temp"]),
borderColor: "rgba(168,85,247,1)",
backgroundColor: "rgba(168,85,247,0.5)",
fill: false,
},
{
label: "CPU Temp",
data: history.map((h) => Number(formatValue(h["CPU Temp"]))),
borderColor: "rgba(251,191,36,1)",
backgroundColor: "rgba(251,191,36,0.5)",
fill: false,
},
];
const baseChartOptions = {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: false,
grid: {
color: "rgba(200,200,200,0.2)",
},
title: {
display: true,
text: "Wert",
},
},
x: {
grid: {
color: "rgba(200,200,200,0.2)",
},
title: {
display: true,
text: "Zeit",
},
},
},
plugins: {
legend: {
position: "bottom" as const,
},
tooltip: {
callbacks: {
label: function (context: TooltipItem<"line">) {
const label = context.dataset.label || "";
const value =
context.parsed.y !== null ? context.parsed.y.toFixed(2) : "";
const unit = label.includes("Temp") ? "°C" : "V";
return `${label}: ${value} ${unit}`;
},
},
},
},
const handleCloseDetail = () => {
setSelectedKey(null);
setIsModalOpen(false);
};
return (
@@ -142,55 +62,15 @@ const SystemPage = () => {
<h1 className="text-xl font-bold mb-4">
System Spannungen & Temperaturen
</h1>
<div className="grid grid-cols-2 gap-4 mb-8">
{Object.entries(voltages).map(([key, value]) => {
const formattedValue = formatValue(value);
const unit = key.includes("Temp") ? "°C" : "V";
return (
<div key={key} className="p-4 border rounded shadow">
<h2 className="font-semibold">{key}</h2>
<p>
{formattedValue} {unit}
</p>
</div>
);
})}
</div>
<div className="grid grid-cols-1 xl:grid-cols-2 gap-8">
<div className="h-[300px]">
<Line
data={{ labels, datasets: voltageDatasets }}
options={{
...baseChartOptions,
plugins: {
...baseChartOptions.plugins,
title: {
display: true,
text: "Systemspannungen",
},
},
}}
/>
</div>
<div className="h-[300px]">
<Line
data={{ labels, datasets: temperatureDatasets }}
options={{
...baseChartOptions,
plugins: {
...baseChartOptions.plugins,
title: {
display: true,
text: "Systemtemperaturen",
},
},
}}
/>
</div>
</div>
<SystemOverviewGrid voltages={voltages} onOpenDetail={handleOpenDetail} />
<SystemCharts history={history} zeitraum={zeitraum} />
<DetailModal
isOpen={isModalOpen}
selectedKey={selectedKey}
onClose={handleCloseDetail}
zeitraum={zeitraum}
setZeitraum={setZeitraum}
/>
</div>
);
};

View File

@@ -1,3 +1,10 @@
{
"win_systemVoltTemp": ["AAV09", "AAV11", "AAV15", "AAV16", "AAV17", "AAV18"]
"win_systemVoltTemp": [
"<%=AAV09%>",
"<%=AAV11%>",
"<%=AAV15%>",
"<%=AAV16%>",
"<%=AAV17%>",
"<%=AAV18%>"
]
}

17
public/CPL/js/abfrage.js Normal file
View File

@@ -0,0 +1,17 @@
// window-Funktion, damit sie global im Browser verfügbar ist
window.startAbfrage = function (fromDate, toDate, quelle, typ) {
// Datum formatieren: yyyy;MM;dd
const format = (dateStr) => {
const d = new Date(dateStr);
return `${d.getFullYear()};${d.getMonth() + 1};${d.getDate()}`;
};
const von = format(fromDate);
const bis = format(toDate);
// Beispiel-Kanal: 110 = +5V
const diaURL = `/cpl?/dashboard.html&DIA1=${von};${bis};${quelle};${typ};`;
// Neue Seite öffnen
window.open(diaURL, "_blank");
};

View File

@@ -0,0 +1,50 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { getSystemspannung15VminusThunk } from "../thunks/getSystemspannung15VminusThunk";
type StateType = {
DIA0: unknown[];
DIA1: unknown[];
DIA2: unknown[];
isLoading: boolean;
error: string | null;
};
const initialState: StateType = {
DIA0: [],
DIA1: [],
DIA2: [],
isLoading: false,
error: null,
};
export const systemspannung15VminusSlice = createSlice({
name: "systemspannung15Vminus",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getSystemspannung15VminusThunk.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(
getSystemspannung15VminusThunk.fulfilled,
(
state,
action: PayloadAction<{
typ: "DIA0" | "DIA1" | "DIA2";
data: unknown[];
}>
) => {
state.isLoading = false;
state[action.payload.typ] = action.payload.data;
}
)
.addCase(getSystemspannung15VminusThunk.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload as string;
});
},
});
export default systemspannung15VminusSlice.reducer;

View File

@@ -0,0 +1,50 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { getSystemspannung15VplusThunk } from "../thunks/getSystemspannung15VplusThunk";
type StateType = {
DIA0: unknown[];
DIA1: unknown[];
DIA2: unknown[];
isLoading: boolean;
error: string | null;
};
const initialState: StateType = {
DIA0: [],
DIA1: [],
DIA2: [],
isLoading: false,
error: null,
};
export const systemspannung15VplusSlice = createSlice({
name: "systemspannung15Vplus",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getSystemspannung15VplusThunk.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(
getSystemspannung15VplusThunk.fulfilled,
(
state,
action: PayloadAction<{
typ: "DIA0" | "DIA1" | "DIA2";
data: unknown[];
}>
) => {
state.isLoading = false;
state[action.payload.typ] = action.payload.data;
}
)
.addCase(getSystemspannung15VplusThunk.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload as string;
});
},
});
export default systemspannung15VplusSlice.reducer;

View File

@@ -0,0 +1,51 @@
// redux/slices/systemspannung5VplusSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { getSystemspannung5VplusThunk } from "../thunks/getSystemspannung5VplusThunk";
type StateType = {
DIA0: unknown[]; // alle Werte
DIA1: unknown[]; // stündlich
DIA2: unknown[]; // täglich
isLoading: boolean;
error: string | null;
};
const initialState: StateType = {
DIA0: [],
DIA1: [],
DIA2: [],
isLoading: false,
error: null,
};
export const systemspannung5VplusSlice = createSlice({
name: "systemspannung5Vplus",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getSystemspannung5VplusThunk.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(
getSystemspannung5VplusThunk.fulfilled,
(
state,
action: PayloadAction<{
typ: "DIA0" | "DIA1" | "DIA2";
data: unknown[];
}>
) => {
state.isLoading = false;
state[action.payload.typ] = action.payload.data;
}
)
.addCase(getSystemspannung5VplusThunk.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload as string;
});
},
});
export default systemspannung5VplusSlice.reducer;

View File

@@ -0,0 +1,50 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { getSystemspannung98VminusThunk } from "../thunks/getSystemspannung98VminusThunk";
type StateType = {
DIA0: unknown[];
DIA1: unknown[];
DIA2: unknown[];
isLoading: boolean;
error: string | null;
};
const initialState: StateType = {
DIA0: [],
DIA1: [],
DIA2: [],
isLoading: false,
error: null,
};
export const systemspannung98VminusSlice = createSlice({
name: "systemspannung98Vminus",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getSystemspannung98VminusThunk.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(
getSystemspannung98VminusThunk.fulfilled,
(
state,
action: PayloadAction<{
typ: "DIA0" | "DIA1" | "DIA2";
data: unknown[];
}>
) => {
state.isLoading = false;
state[action.payload.typ] = action.payload.data;
}
)
.addCase(getSystemspannung98VminusThunk.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload as string;
});
},
});
export default systemspannung98VminusSlice.reducer;

View File

@@ -0,0 +1,50 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { getTemperaturAdWandlerThunk } from "../thunks/getTemperaturAdWandlerThunk";
type StateType = {
DIA0: unknown[];
DIA1: unknown[];
DIA2: unknown[];
isLoading: boolean;
error: string | null;
};
const initialState: StateType = {
DIA0: [],
DIA1: [],
DIA2: [],
isLoading: false,
error: null,
};
export const temperaturAdWandlerSlice = createSlice({
name: "temperaturAdWandler",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getTemperaturAdWandlerThunk.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(
getTemperaturAdWandlerThunk.fulfilled,
(
state,
action: PayloadAction<{
typ: "DIA0" | "DIA1" | "DIA2";
data: unknown[];
}>
) => {
state.isLoading = false;
state[action.payload.typ] = action.payload.data;
}
)
.addCase(getTemperaturAdWandlerThunk.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload as string;
});
},
});
export default temperaturAdWandlerSlice.reducer;

View File

@@ -0,0 +1,50 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { getTemperaturProzessorThunk } from "../thunks/getTemperaturProzessorThunk";
type StateType = {
DIA0: unknown[];
DIA1: unknown[];
DIA2: unknown[];
isLoading: boolean;
error: string | null;
};
const initialState: StateType = {
DIA0: [],
DIA1: [],
DIA2: [],
isLoading: false,
error: null,
};
export const temperaturProzessorSlice = createSlice({
name: "temperaturProzessor",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getTemperaturProzessorThunk.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(
getTemperaturProzessorThunk.fulfilled,
(
state,
action: PayloadAction<{
typ: "DIA0" | "DIA1" | "DIA2";
data: unknown[];
}>
) => {
state.isLoading = false;
state[action.payload.typ] = action.payload.data;
}
)
.addCase(getTemperaturProzessorThunk.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload as string;
});
},
});
export default temperaturProzessorSlice.reducer;

View File

@@ -29,6 +29,12 @@ import messagesReducer from "./slices/messagesSlice";
import firmwareUpdateReducer from "@/redux/slices/firmwareUpdateSlice";
import confirmModalReducer from "./slices/confirmModalSlice";
import firmwareProgressReducer from "./slices/firmwareProgressSlice";
import systemspannung5VplusReducer from "./slices/systemspannung5VplusSlice";
import systemspannung15VminusReducer from "./slices/systemspannung15VminusSlice";
import systemspannung15VplusReducer from "./slices/systemspannung15VplusSlice";
import systemspannung98VminusReducer from "./slices/systemspannung98VminusSlice";
import temperaturAdWandlerReducer from "./slices/temperaturAdWandlerSlice";
import temperaturProzessorReducer from "./slices/temperaturProzessorSlice";
const store = configureStore({
reducer: {
@@ -60,6 +66,12 @@ const store = configureStore({
firmwareUpdate: firmwareUpdateReducer,
confirmModal: confirmModalReducer,
firmwareProgress: firmwareProgressReducer,
systemspannung5Vplus: systemspannung5VplusReducer,
systemspannung15Vminus: systemspannung15VminusReducer,
systemspannung15Vplus: systemspannung15VplusReducer,
systemspannung98Vminus: systemspannung98VminusReducer,
temperaturAdWandler: temperaturAdWandlerReducer,
temperaturProzessor: temperaturProzessorReducer,
},
});

View File

@@ -0,0 +1,15 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchSystemspannung15VminusService } from "@/services/fetchSystemspannung15VminusService";
export const getSystemspannung15VminusThunk = createAsyncThunk(
"systemspannung15Vminus/fetch",
async (typ: "DIA0" | "DIA1" | "DIA2", thunkAPI) => {
try {
const data = await fetchSystemspannung15VminusService(typ);
return { typ, data };
} catch (error) {
console.error("Fehler in getSystemspannung15VminusThunk:", error);
return thunkAPI.rejectWithValue("Fehler beim Laden der -15V-Daten");
}
}
);

View File

@@ -0,0 +1,15 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchSystemspannung15VplusService } from "@/services/fetchSystemspannung15VplusService";
export const getSystemspannung15VplusThunk = createAsyncThunk(
"systemspannung15Vplus/fetch",
async (typ: "DIA0" | "DIA1" | "DIA2", thunkAPI) => {
try {
const data = await fetchSystemspannung15VplusService(typ);
return { typ, data };
} catch (error) {
console.error("Fehler in getSystemspannung15VplusThunk:", error);
return thunkAPI.rejectWithValue("Fehler beim Laden der +15V-Daten");
}
}
);

View File

@@ -0,0 +1,16 @@
// redux/thunks/getSystemspannung5VplusThunk.ts
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchSystemspannung5VplusService } from "@/services/fetchSystemspannung5VplusService";
export const getSystemspannung5VplusThunk = createAsyncThunk(
"systemspannung5Vplus/fetch",
async (typ: "DIA0" | "DIA1" | "DIA2", thunkAPI) => {
try {
const data = await fetchSystemspannung5VplusService(typ);
return { typ, data };
} catch (error) {
console.error("Fehler in getSystemspannung5VplusThunk:", error);
return thunkAPI.rejectWithValue("Fehler beim Laden der 5V-Daten");
}
}
);

View File

@@ -0,0 +1,15 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchSystemspannung98VminusService } from "@/services/fetchSystemspannung98VminusService";
export const getSystemspannung98VminusThunk = createAsyncThunk(
"systemspannung98Vminus/fetch",
async (typ: "DIA0" | "DIA1" | "DIA2", thunkAPI) => {
try {
const data = await fetchSystemspannung98VminusService(typ);
return { typ, data };
} catch (error) {
console.error("Fehler in getSystemspannung98VminusThunk:", error);
return thunkAPI.rejectWithValue("Fehler beim Laden der -98V-Daten");
}
}
);

View File

@@ -0,0 +1,15 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchTemperaturAdWandlerService } from "@/services/fetchTemperaturAdWandlerService";
export const getTemperaturAdWandlerThunk = createAsyncThunk(
"temperaturAdWandler/fetch",
async (typ: "DIA0" | "DIA1" | "DIA2", thunkAPI) => {
try {
const data = await fetchTemperaturAdWandlerService(typ);
return { typ, data };
} catch (error) {
console.error("Fehler in getTemperaturAdWandlerThunk:", error);
return thunkAPI.rejectWithValue("Fehler beim Laden der Temperaturdaten");
}
}
);

View File

@@ -0,0 +1,17 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchTemperaturProzessorService } from "@/services/fetchTemperaturProzessorService";
export const getTemperaturProzessorThunk = createAsyncThunk(
"temperaturProzessor/fetch",
async (typ: "DIA0" | "DIA1" | "DIA2", thunkAPI) => {
try {
const data = await fetchTemperaturProzessorService(typ);
return { typ, data };
} catch (error) {
console.error("Fehler in getTemperaturProzessorThunk:", error);
return thunkAPI.rejectWithValue(
"Fehler beim Laden der Prozessor-Temperaturdaten"
);
}
}
);

View File

@@ -1,7 +1,7 @@
// services/fetchAnalogInputsHistoryService.ts
export async function fetchAnalogInputsHistoryService(): Promise<
Record<number, any[]>
Record<number, unknown[]>
> {
const today = new Date();
const yesterday = new Date(today);
@@ -16,7 +16,7 @@ export async function fetchAnalogInputsHistoryService(): Promise<
const fromDate = formatDate(yesterday);
const toDate = formatDate(today);
const result: Record<number, any[]> = {};
const result: Record<number, unknown[]> = {};
const isDev = process.env.NODE_ENV === "development";

View File

@@ -0,0 +1,27 @@
/**
* Holt Messwerte für -15V aus der passenden JSON-Datei über die API
* @param type - Typ der Daten: DIA0 = alle, DIA1 = stündlich, DIA2 = täglich
*/
export const fetchSystemspannung15VminusService = async (
type: "DIA0" | "DIA1" | "DIA2"
) => {
try {
const isDev = process.env.NODE_ENV === "development";
const channel = 114; // 114 = -15V laut Spezifikation
const from = "2025;01;01";
const to = "2025;07;31";
const path = isDev
? `/api/cpl/getSystemspannung15VminusHandler?typ=${type}`
: `/cpl?/dashboard.html&${type}=${from};${to};${channel};1;`;
const res = await fetch(path);
if (!res.ok) throw new Error("❌ Fehler beim Abrufen der -15V-Daten");
return await res.json();
} catch (err) {
console.error("❌ Fehler in fetchSystemspannung15VminusService:", err);
return null;
}
};

View File

@@ -0,0 +1,27 @@
/**
* Holt Messwerte für +15V aus der passenden JSON-Datei über die API
* @param type - Typ der Daten: DIA0 = alle, DIA1 = stündlich, DIA2 = täglich
*/
export const fetchSystemspannung15VplusService = async (
type: "DIA0" | "DIA1" | "DIA2"
) => {
try {
const isDev = process.env.NODE_ENV === "development";
const channel = 108; // 108 = +15V laut Spezifikation
const from = "2025;01;01";
const to = "2025;07;31";
const path = isDev
? `/api/cpl/getSystemspannung15VplusHandler?typ=${type}`
: `/cpl?/dashboard.html&${type}=${from};${to};${channel};1;`;
const res = await fetch(path);
if (!res.ok) throw new Error("❌ Fehler beim Abrufen der +15V-Daten");
return await res.json();
} catch (err) {
console.error("❌ Fehler in fetchSystemspannung15VplusService:", err);
return null;
}
};

View File

@@ -0,0 +1,29 @@
// services/fetchSystemspannung5VplusService.ts
/**
* Holt Messwerte für +5V aus der passenden JSON-Datei über die API
* @param typ - Typ der Daten: DIA0 = alle, DIA1 = stündlich, DIA2 = täglich
*/
export const fetchSystemspannung5VplusService = async (
type: "DIA0" | "DIA1" | "DIA2"
) => {
try {
const isDev = process.env.NODE_ENV === "development";
const channel = 110; // 110 = +5V
const from = "2025;01;01";
const to = "2025;07;31";
const path = isDev
? `/api/cpl/getSystemspannung5VplusHandler?typ=${type}`
: `/cpl?/dashboard.html&${type}=${from};${to};${channel};1;`;
const res = await fetch(path);
if (!res.ok) throw new Error("❌ Fehler beim Abrufen der +5V-Daten");
return await res.json();
} catch (err) {
console.error("❌ Fehler in fetchSystemspannung5VplusService:", err);
return null;
}
};

View File

@@ -0,0 +1,27 @@
/**
* Holt Messwerte für -98V aus der passenden JSON-Datei über die API
* @param type - Typ der Daten: DIA0 = alle, DIA1 = stündlich, DIA2 = täglich
*/
export const fetchSystemspannung98VminusService = async (
type: "DIA0" | "DIA1" | "DIA2"
) => {
try {
const isDev = process.env.NODE_ENV === "development";
const channel = 115; // 115 = -98V laut Spezifikation
const from = "2025;01;01";
const to = "2025;07;31";
const path = isDev
? `/api/cpl/getSystemspannung98VminusHandler?typ=${type}`
: `/cpl?/dashboard.html&${type}=${from};${to};${channel};1;`;
const res = await fetch(path);
if (!res.ok) throw new Error("❌ Fehler beim Abrufen der -98V-Daten");
return await res.json();
} catch (err) {
console.error("❌ Fehler in fetchSystemspannung98VminusService:", err);
return null;
}
};

View File

@@ -0,0 +1,30 @@
/**
* Holt Temperaturwerte vom AD-Wandler aus der passenden JSON-Datei über die API
* @param type - Typ der Daten: DIA0 = alle, DIA1 = stündlich, DIA2 = täglich
*/
export const fetchTemperaturAdWandlerService = async (
type: "DIA0" | "DIA1" | "DIA2"
) => {
try {
const isDev = process.env.NODE_ENV === "development";
const channel = 116; // 116 = Temperatur AD-Wandler laut Spezifikation
const from = "2025;01;01";
const to = "2025;07;31";
const path = isDev
? `/api/cpl/getTemperaturAdWandlerHandler?typ=${type}`
: `/cpl?/dashboard.html&${type}=${from};${to};${channel};1;`;
const res = await fetch(path);
if (!res.ok)
throw new Error(
"❌ Fehler beim Abrufen der Temperaturdaten (AD-Wandler)"
);
return await res.json();
} catch (err) {
console.error("❌ Fehler in fetchTemperaturAdWandlerService:", err);
return null;
}
};

View File

@@ -0,0 +1,28 @@
/**
* Holt Temperaturwerte vom Prozessor aus der passenden JSON-Datei über die API
* @param type - Typ der Daten: DIA0 = alle, DIA1 = stündlich, DIA2 = täglich
*/
export const fetchTemperaturProzessorService = async (
type: "DIA0" | "DIA1" | "DIA2"
) => {
try {
const isDev = process.env.NODE_ENV === "development";
const channel = 117; // 117 = Temperatur Prozessor laut Spezifikation
const from = "2025;01;01";
const to = "2025;07;31";
const path = isDev
? `/api/cpl/getTemperaturProzessorHandler?typ=${type}`
: `/cpl?/dashboard.html&${type}=${from};${to};${channel};1;`;
const res = await fetch(path);
if (!res.ok)
throw new Error("❌ Fehler beim Abrufen der Temperaturdaten (Prozessor)");
return await res.json();
} catch (err) {
console.error("❌ Fehler in fetchTemperaturProzessorService:", err);
return null;
}
};