$url, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 3, CURLOPT_CONNECTTIMEOUT => 2 ]); $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return ($http_code === 200 && $response) ? json_decode($response, true) : null; } function calculateBackgroundColor() { $lat = 50.8009; $lon = 11.5875; $dayColor = [224, 224, 224]; $nightColor = [96, 96, 96]; $twilightDuration = 2; $now = time(); $sunrise = date_sunrise($now, SUNFUNCS_RET_TIMESTAMP, $lat, $lon); $sunset = date_sunset($now, SUNFUNCS_RET_TIMESTAMP, $lat, $lon); $current_hour = (float)date('G') + ((float)date('i') / 60); $sunrise_hour = (float)date('G', $sunrise) + ((float)date('i', $sunrise) / 60); $sunset_hour = (float)date('G', $sunset) + ((float)date('i', $sunset) / 60); $t = 0; if ($current_hour >= $sunset_hour && $current_hour <= $sunset_hour + $twilightDuration) { $t = ($current_hour - $sunset_hour) / $twilightDuration; } elseif ($current_hour >= $sunrise_hour - $twilightDuration && $current_hour < $sunrise_hour) { $t = 1 - (($current_hour - ($sunrise_hour - $twilightDuration)) / $twilightDuration); } elseif ($current_hour < $sunrise_hour - $twilightDuration || $current_hour > $sunset_hour + $twilightDuration) { $t = 1; } $r = round($dayColor[0] + ($nightColor[0] - $dayColor[0]) * $t); $g = round($dayColor[1] + ($nightColor[1] - $dayColor[1]) * $t); $b = round($dayColor[2] + ($nightColor[2] - $dayColor[2]) * $t); return "rgb($r,$g,$b)"; } function calculateBatteryRuntime($usable_energy, $power_display, $battery_reserve_percent) { if ($power_display >= 0 || $usable_energy <= 0) return '-'; $power_kw = abs($power_display) / 1000; if ($power_kw <= 0) return '-'; $runtime_hours = $usable_energy / $power_kw; $end_time = time() + ($runtime_hours * 3600); $german_weekdays = ['Sun' => 'So', 'Mon' => 'Mo', 'Tue' => 'Di', 'Wed' => 'Mi', 'Thu' => 'Do', 'Fri' => 'Fr', 'Sat' => 'Sa']; $weekday_german = $german_weekdays[date('D', $end_time)] ?? date('D', $end_time); return date('H:i', $end_time) . " Uhr
" . $weekday_german . ". " . date('d.m.y', $end_time); } function getBatteryStatusText($power_display, $usable_soc) { if ($power_display > 0) return ['label' => 'Akku:', 'value' => 'wird geladen']; if ($power_display == 0 && $usable_soc > 0 && $usable_soc <= 2) return ['label' => 'Akku:', 'value' => 'warten auf Ladung']; if ($usable_soc <= 0) return ['label' => 'Akku ist leer:', 'value' => 'Netzbezug']; return ['label' => 'Akku reicht bei aktuellem
Verbrauch bis circa:', 'value' => '']; } function getBatteryIcon($soc) { if ($soc <= 15) return ''; if ($soc <= 25) return ''; if ($soc <= 50) return ''; if ($soc <= 75) return ''; return ''; } function format_duration($seconds) { if (!$seconds || $seconds <= 0) return "–"; $h = floor($seconds / 3600); $m = floor(($seconds % 3600) / 60); $s = $seconds % 60; return sprintf("%02d:%02d:%02d", $h, $m, $s); } function translate_mode($mode) { $map = ['off' => 'Aus', 'pv' => 'PV', 'minpv' => 'Min+PV', 'now' => 'Schnell']; return $map[strtolower($mode)] ?? ucfirst($mode); } // Datenabruf $data_3em = fetchShellyData($endpoint_3em); $data_pv = fetchShellyData($endpoint_pv); $data_3em_63t = fetchShellyData($endpoint_3em_63t); $data_3em_63w = fetchShellyData($endpoint_3em_63w); $evcc_data = @file_get_contents($evcc_url); $data_evcc = $evcc_data ? json_decode($evcc_data, true) : null; $loadpoint = $data_evcc['loadpoints'][0] ?? []; $battery = $data_evcc['battery'][0] ?? null; // Strom und Phasen aus EVCC $avg_current = null; $phase_text = ''; if ($data_evcc && !empty($loadpoint)) { $currents = $loadpoint['chargeCurrents'] ?? null; if (is_array($currents) && count($currents) == 3) { $valid_currents = array_filter($currents, fn($c) => $c > 0.1); $avg_current = !empty($valid_currents) ? array_sum($valid_currents) / count($valid_currents) : 0; } $phases_active = $loadpoint['phasesActive'] ?? 0; if ($phases_active == 1) $phase_text = "1‑phasig"; elseif ($phases_active == 3) $phase_text = "3‑phasig"; elseif ($phases_active > 0) $phase_text = $phases_active . "‑phasig"; } // Netzanschluss-Daten if ($data_3em && isset($data_3em["em:0"])) { $em1 = $data_3em["em:0"]; $act_power_3em = (float)$em1["total_act_power"]; $voltage_avg_3em = ($em1["a_voltage"] + $em1["b_voltage"] + $em1["c_voltage"]) / 3; $freq_3em = (float)$em1["a_freq"]; $pf_avg_3em = ($em1["a_pf"] + $em1["b_pf"] + $em1["c_pf"]) / 3; $eff_current_3em = $voltage_avg_3em > 0 ? abs($act_power_3em / $voltage_avg_3em) : 0; $act_power_f_3em = number_format($act_power_3em, 1, ',', '.'); $voltage_f_3em = number_format($voltage_avg_3em, 1, ',', ''); $freq_f_3em = number_format($freq_3em, 2, ',', ''); $pf_f_3em = number_format($pf_avg_3em, 2, ',', ''); $eff_current_f_3em = number_format($eff_current_3em, 2, ',', ''); } else { $act_power_3em = 0; $act_power_f_3em = $voltage_f_3em = $freq_f_3em = $pf_f_3em = $eff_current_f_3em = "Fehler"; } // PV-Daten if ($data_pv) { $act_power_pv = abs($data_pv['em1:0']['act_power'] ?? 0); $current_pv = number_format(($data_pv['em1:0']['current'] ?? 0), 2, ',', ''); $voltage_pv = number_format(($data_pv['em1:0']['voltage'] ?? 0), 1, ',', ''); $freq_pv = number_format(($data_pv['em1:0']['freq'] ?? 0), 2, ',', ''); $pf_pv = number_format(($data_pv['em1:0']['pf'] ?? 0), 2, ',', ''); $power_per_kWp = $pv_kWp > 0 ? $act_power_pv / $pv_kWp : 0; $power_per_kWp_f = number_format($power_per_kWp, 1, ',', '.'); $act_power_formatted_pv = number_format($act_power_pv, 1, ',', '.'); } else { $act_power_pv = 0; $act_power_formatted_pv = $current_pv = $voltage_pv = $freq_pv = $pf_pv = $power_per_kWp_f = "Fehler"; } // 3EM-63T Daten if ($data_3em_63t) { if (isset($data_3em_63t["em1:0"])) { $em1_63t = $data_3em_63t["em1:0"]; $act_power_3em_63t = abs($em1_63t["act_power"] ?? 0); $current_avg_3em_63t = (($em1_63t["a_current"] ?? 0) + ($em1_63t["b_current"] ?? 0) + ($em1_63t["c_current"] ?? 0)) / 3; $voltage_avg_3em_63t = (($em1_63t["a_voltage"] ?? 0) + ($em1_63t["b_voltage"] ?? 0) + ($em1_63t["c_voltage"] ?? 0)) / 3; $freq_3em_63t = $em1_63t["a_freq"] ?? $em1_63t["freq"] ?? 0; $pf_avg_3em_63t = (($em1_63t["a_pf"] ?? 0) + ($em1_63t["b_pf"] ?? 0) + ($em1_63t["c_pf"] ?? 0)) / 3; } elseif (isset($data_3em_63t["em:0"])) { $em1_63t = $data_3em_63t["em:0"]; $act_power_3em_63t = abs($em1_63t["total_act_power"] ?? 0); $current_avg_3em_63t = ($em1_63t["a_current"] + $em1_63t["b_current"] + $em1_63t["c_current"]) / 3; $voltage_avg_3em_63t = ($em1_63t["a_voltage"] + $em1_63t["b_voltage"] + $em1_63t["c_voltage"]) / 3; $freq_3em_63t = $em1_63t["a_freq"] ?? 0; $pf_avg_3em_63t = ($em1_63t["a_pf"] + $em1_63t["b_pf"] + $em1_63t["c_pf"]) / 3; } else { foreach ($data_3em_63t as $key => $value) { if (strpos($key, 'em') === 0 && is_array($value)) { $em1_63t = $value; $act_power_3em_63t = abs($em1_63t["act_power"] ?? $em1_63t["total_act_power"] ?? 0); $current_avg_3em_63t = $em1_63t["a_current"] ?? $em1_63t["current"] ?? 0; $voltage_avg_3em_63t = $em1_63t["a_voltage"] ?? $em1_63t["voltage"] ?? 0; $freq_3em_63t = $em1_63t["a_freq"] ?? $em1_63t["freq"] ?? 0; $pf_avg_3em_63t = $em1_63t["a_pf"] ?? $em1_63t["pf"] ?? 0; break; } } } $act_power_f_3em_63t = number_format($act_power_3em_63t, 1, ',', '.'); $current_f_3em_63t = number_format($current_avg_3em_63t, 2, ',', ''); $voltage_f_3em_63t = number_format($voltage_avg_3em_63t, 1, ',', ''); $freq_f_3em_63t = number_format($freq_3em_63t, 2, ',', ''); $pf_f_3em_63t = number_format($pf_avg_3em_63t, 2, ',', ''); $power_per_kWp_63t = $pv_kWp_63t > 0 ? $act_power_3em_63t / $pv_kWp_63t : 0; $power_per_kWp_f_63t = number_format($power_per_kWp_63t, 1, ',', '.'); } else { $act_power_3em_63t = 0; $act_power_f_3em_63t = $current_f_3em_63t = $voltage_f_3em_63t = $freq_f_3em_63t = $pf_f_3em_63t = $power_per_kWp_f_63t = "Fehler"; } // 3EM-63W Daten if ($data_3em_63w) { if (isset($data_3em_63w["em1:0"])) { $em1_63w = $data_3em_63w["em1:0"]; $act_power_3em_63w = abs($em1_63w["act_power"] ?? 0); $current_avg_3em_63w = (($em1_63w["a_current"] ?? 0) + ($em1_63w["b_current"] ?? 0) + ($em1_63w["c_current"] ?? 0)) / 3; $voltage_avg_3em_63w = (($em1_63w["a_voltage"] ?? 0) + ($em1_63w["b_voltage"] ?? 0) + ($em1_63w["c_voltage"] ?? 0)) / 3; $freq_3em_63w = $em1_63w["a_freq"] ?? $em1_63w["freq"] ?? 0; $pf_avg_3em_63w = (($em1_63w["a_pf"] ?? 0) + ($em1_63w["b_pf"] ?? 0) + ($em1_63w["c_pf"] ?? 0)) / 3; } elseif (isset($data_3em_63w["em:0"])) { $em1_63w = $data_3em_63w["em:0"]; $act_power_3em_63w = abs($em1_63w["total_act_power"] ?? 0); $current_avg_3em_63w = ($em1_63w["a_current"] + $em1_63w["b_current"] + $em1_63w["c_current"]) / 3; $voltage_avg_3em_63w = ($em1_63w["a_voltage"] + $em1_63w["b_voltage"] + $em1_63w["c_voltage"]) / 3; $freq_3em_63w = $em1_63w["a_freq"] ?? 0; $pf_avg_3em_63w = ($em1_63w["a_pf"] + $em1_63w["b_pf"] + $em1_63w["c_pf"]) / 3; } else { foreach ($data_3em_63w as $key => $value) { if (strpos($key, 'em') === 0 && is_array($value)) { $em1_63w = $value; $act_power_3em_63w = abs($em1_63w["act_power"] ?? $em1_63w["total_act_power"] ?? 0); $current_avg_3em_63w = $em1_63w["a_current"] ?? $em1_63w["current"] ?? 0; $voltage_avg_3em_63w = $em1_63w["a_voltage"] ?? $em1_63w["voltage"] ?? 0; $freq_3em_63w = $em1_63w["a_freq"] ?? $em1_63w["freq"] ?? 0; $pf_avg_3em_63w = $em1_63w["a_pf"] ?? $em1_63w["pf"] ?? 0; break; } } } $act_power_f_3em_63w = number_format($act_power_3em_63w, 1, ',', '.'); $current_f_3em_63w = number_format($current_avg_3em_63w, 2, ',', ''); $voltage_f_3em_63w = number_format($voltage_avg_3em_63w, 1, ',', ''); $freq_f_3em_63w = number_format($freq_3em_63w, 2, ',', ''); $pf_f_3em_63w = number_format($pf_avg_3em_63w, 2, ',', ''); $power_per_kWp_63w = $pv_kWp_63w > 0 ? $act_power_3em_63w / $pv_kWp_63w : 0; $power_per_kWp_f_63w = number_format($power_per_kWp_63w, 1, ',', '.'); } else { $act_power_3em_63w = 0; $act_power_f_3em_63w = $current_f_3em_63w = $voltage_f_3em_63w = $freq_f_3em_63w = $pf_f_3em_63w = $power_per_kWp_f_63w = "Fehler"; } // EVCC-Daten verarbeiten if ($data_evcc) { $tarif_price = $data_evcc['tariffGrid'] ?? null; $tarif_display = ($tarif_price !== null) ? "Ladekosten-Summe (gerundet): Preis aktuell: " . number_format(round($tarif_price + 0.005, 2), 2, ',', '.') . " €/kWh." : "Tarif nicht verfügbar"; $soc = $battery['soc'] ?? 0; $battery_fill = max(0, min(100, $soc)); $connected = !empty($loadpoint['connected']); $charging = !empty($loadpoint['charging']); $power_evcc = $loadpoint['chargePower'] ?? 0; $chargedEnergy = $loadpoint['chargedEnergy'] ?? 0; $modeRaw = htmlspecialchars($loadpoint['mode'] ?? 'Unbekannt'); $mode = translate_mode($modeRaw); $vehicle = htmlspecialchars($loadpoint['vehicleTitle'] ?? ($loadpoint['vehicleName'] ?? '')); $duration = format_duration($loadpoint['chargeDuration'] ?? 0); $charged_kwh = $chargedEnergy / 1000.0; $tarif_display_value = ($tarif_price !== null) ? round($tarif_price + 0.005, 2) : 0; $preis_anzeige = round($charged_kwh * $tarif_display_value, 2); if ($charging) { $statusText = " lädt"; $statusColor = "orange"; } elseif ($connected) { $statusText = "🚗 verbunden"; $statusColor = "#222"; } else { $statusText = " frei"; $statusColor = "green"; } $capacity = $battery['capacity'] ?? 0; $power_raw = $battery['power'] ?? 0; $power_display = -1 * $power_raw; $factor = $capacity / 100; $energy_total = $soc * $factor; $usable_soc = max(0, $soc - $battery_reserve_percent); $usable_energy = $usable_soc * $factor; $power_sign = $power_display >= 0 ? "+" : "-"; $soc_display = (round($soc, 1) == round($soc)) ? number_format($soc, 0, ',', '.') : number_format($soc, 1, ',', '.'); $usable_soc_display = (round($usable_soc, 1) == round($usable_soc)) ? number_format($usable_soc, 0, ',', '.') : number_format($usable_soc, 1, ',', '.'); $battery_runtime = calculateBatteryRuntime($usable_energy, $power_display, $battery_reserve_percent); $battery_status = getBatteryStatusText($power_display, $usable_soc); $battery_icon = getBatteryIcon($soc); } else { $statusText = "⚠️ EVCC nicht erreichbar"; $statusColor = "red"; $power_evcc = $soc = $battery_fill = 0; $battery_runtime = '-'; $battery_status = ['label' => 'Akku:', 'value' => 'Daten nicht verfügbar']; $battery_icon = ''; $mode = 'Unbekannt'; $duration = '–'; } $backgroundColor = calculateBackgroundColor(); $timestamp = date("d.m.Y H:i:s"); $title_power_3em = ($act_power_3em >= 0 ? '+' : '') . $act_power_f_3em; $title_power_pv = ($act_power_pv > 0 ? '+' : '') . $act_power_formatted_pv; $total_pv_power = $act_power_pv + $act_power_3em_63t + $act_power_3em_63w; // AJAX-Ausgabe if ($isAjax) { ob_clean(); ?>
Wirkleistung (W)
Bezug + bzw. /Einspeisung - : 
 W 
Stromstärke (A)
aus Wirkleistung berechnet: 
 A 
Spannung (V)
Durchschnitt der 3‑Phasen: 
 V 
Frequenz (Hz) Netzfrequenz:  Hz
Leistungsfaktor (pf)
Durchschnitt der 3‑Phasen: 
 pf
Wirkleistung (W)
Nutzbare Leistung im Hausnetz:  
 W 
Stromstärke (A)
Fließender Strom:  
 A 
Spannung (V) Netzspannung:   V 
Frequenz (Hz) Netzfrequenz:   Hz
Leistungsfaktor (pf)
Verhältnis Wirk‑ zu Scheinleistung:  
 pf
PV‑Leistung
pro kWp (W/kWp):  
 W/kWp
Wirkleistung (W)
Nutzbare Leistung im Hausnetz:  
0 ? '+' : '') . $act_power_f_3em_63t) ?> W 
Stromstärke (A)
Durchschnitt der 3‑Phasen:  
 A 
Spannung (V)
Durchschnitt der 3‑Phasen: 
 V 
Frequenz (Hz) Netzfrequenz:   Hz
Leistungsfaktor (pf)
Durchschnitt der 3‑Phasen:  
 pf
PV‑Leistung
pro kWp (W/kWp):  
 W/kWp
Wirkleistung (W)
Nutzbare Leistung im Hausnetz:  
0 ? '+' : '') . $act_power_f_3em_63w) ?> W 
Stromstärke (A)
Durchschnitt der 3‑Phasen:  
 A 
Spannung (V)
Durchschnitt der 3‑Phasen: 
 V 
Frequenz (Hz) Netzfrequenz:   Hz
Leistungsfaktor (pf)
Durchschnitt der 3‑Phasen:  
 pf
PV‑Leistung
pro kWp (W/kWp):  
 W/kWp
✅ frei"): ?>
Wallbox-Nutzung auf Anfrage möglich.
Die Daten der letzten Ladung werden unten weiterhin angezeigt.
Status:
✅ frei"): ?>
Fahrzeug:
Modus:
Ladeleistung aktuell: kWh
Stromstärke (∅): A
Ladeart:
Geladen: kWh

PV-Erträge sind unberücksichtigt.
 €  
Ladedauer:
Fahrzeug:Kein Fahrzeug erkannt" ?>
Modus:
Ladeleistung aktuell: kWh
Stromstärke (∅): A  
Ladeart:
Geladen: kWh

PV-Erträge sind unberücksichtigt.
 €  
Ladedauer:
⚠️ Keine Ladepunkte gefunden.
Speicherkapazität (nutzbar): kWh
Akkustand (SoC): %  
Aktuell verfügbar: kWh
Lade- (+) Entladeleistung (-): W  
Nutzbar
abzgl.  % Reserve:
 %  
 kWh
Keine Batteriedaten verfügbar.
<?= htmlspecialchars($title_power_3em) ?> W / <?= htmlspecialchars(number_format($total_pv_power, 1, ',', '.')) ?> W Netz- & PV-Leistung
Netzanschluss:
(Pro 3EM 120A)
Wirkleistung (W)
Bezug + bzw. /Einspeisung - : 
 W 
Stromstärke (A)
aus Wirkleistung berechnet: 
 A 
Spannung (V)
Durchschnitt der 3‑Phasen: 
 V 
Frequenz (Hz) Netzfrequenz:  Hz
Leistungsfaktor (pf)
Durchschnitt der 3‑Phasen: 
 pf
PV:
Dach (Pro EM-50)
Wirkleistung (W)
Nutzbare Leistung im Hausnetz:  
 W 
Stromstärke (A)
Fließender Strom:  
 A 
Spannung (V) Netzspannung:   V 
Frequenz (Hz) Netzfrequenz:   Hz
Leistungsfaktor (pf)
Verhältnis Wirk‑ zu Scheinleistung:  
 pf
PV‑Leistung
pro kWp (W/kWp):  
 W/kWp
PV:
Fassade (3EM-63T)
Wirkleistung (W)
Nutzbare Leistung im Hausnetz:  
0 ? '+' : '') . $act_power_f_3em_63t) ?> W 
Stromstärke (A)
Durchschnitt der 3‑Phasen:  
 A 
Spannung (V)
Durchschnitt der 3‑Phasen: 
 V 
Frequenz (Hz) Netzfrequenz:   Hz
Leistungsfaktor (pf)
Durchschnitt der 3‑Phasen:  
 pf
PV‑Leistung
pro kWp (W/kWp):  
 W/kWp
PV:
Garage (3EM-63W)
Wirkleistung (W)
Nutzbare Leistung im Hausnetz:  
0 ? '+' : '') . $act_power_f_3em_63w) ?> W 
Stromstärke (A)
Durchschnitt der 3‑Phasen:  
 A 
Spannung (V)
Durchschnitt der 3‑Phasen: 
 V 
Frequenz (Hz) Netzfrequenz:   Hz
Leistungsfaktor (pf)
Durchschnitt der 3‑Phasen:  
 pf
PV‑Leistung
pro kWp (W/kWp):  
 W/kWp
Wallbox:
✅ frei"): ?>
Wallbox-Nutzung auf Anfrage möglich.
Die Daten der letzten Ladung werden unten weiterhin angezeigt.
Status:
✅ frei"): ?>
Fahrzeug:
Fahrzeug:Kein Fahrzeug erkannt" ?>
Modus:
Leistung: W  
Stromstärke (∅): A
Ladeart:
Geladen: kWh

PV-Erträge sind unberücksichtigt.
 €  
Ladedauer:
⚠️ Keine Ladepunkte gefunden.
Stromspeicher:
Speicherkapazität (nutzbar): kWh
Akkustand (SoC): %  
Aktuell verfügbar: kWh
Lade- (+) Entladeleistung (-): W  
Nutzbar
abzgl.  % Reserve:
 %  
 kWh
Keine Batteriedaten verfügbar.