This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixEMS;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Verteilt eine gemeinsame Einspeisegrenze auf regelbare PV-Wechselrichter.
|
||||
*
|
||||
* Netzleistung: positiv Bezug, negativ Einspeisung.
|
||||
*/
|
||||
final class EinspeiseRegler
|
||||
{
|
||||
/**
|
||||
* @param list<array{ID: string, Nennleistung_W: float|int, Istleistung_W: float|int}> $wechselrichter
|
||||
* @param array<string, float|int> $letzteGrenzen
|
||||
* @return array{
|
||||
* Netzabweichung_W: float,
|
||||
* ZielGesamtleistung_W: float,
|
||||
* Abregelbedarf_W: float,
|
||||
* Grenzen_W: array<string, float>
|
||||
* }
|
||||
*/
|
||||
public static function verteile(
|
||||
float $netzleistung,
|
||||
float $einspeisegrenze,
|
||||
float $toleranz,
|
||||
array $wechselrichter,
|
||||
array $letzteGrenzen = []
|
||||
): array {
|
||||
if ($einspeisegrenze < 0.0) {
|
||||
throw new InvalidArgumentException('Einspeisegrenze darf nicht negativ sein.');
|
||||
}
|
||||
if ($toleranz < 0.0) {
|
||||
throw new InvalidArgumentException('Einspeisetoleranz darf nicht negativ sein.');
|
||||
}
|
||||
if ($wechselrichter === []) {
|
||||
throw new InvalidArgumentException('Mindestens ein regelbarer Wechselrichter ist erforderlich.');
|
||||
}
|
||||
|
||||
$nennleistungGesamt = 0.0;
|
||||
$istleistungGesamt = 0.0;
|
||||
$bisherigeGrenzeGesamt = 0.0;
|
||||
$normalisiert = [];
|
||||
$kennungen = [];
|
||||
|
||||
foreach ($wechselrichter as $eintrag) {
|
||||
$id = $eintrag['ID'] ?? null;
|
||||
$nennleistung = $eintrag['Nennleistung_W'] ?? null;
|
||||
$istleistung = $eintrag['Istleistung_W'] ?? null;
|
||||
if (!is_string($id) || trim($id) === '' || isset($kennungen[$id])) {
|
||||
throw new InvalidArgumentException('Wechselrichter-ID fehlt oder ist mehrfach vorhanden.');
|
||||
}
|
||||
if (!is_numeric($nennleistung) || (float) $nennleistung <= 0.0) {
|
||||
throw new InvalidArgumentException('Wechselrichter-Nennleistung muss groesser als 0 sein.');
|
||||
}
|
||||
if (!is_numeric($istleistung) || (float) $istleistung < 0.0) {
|
||||
throw new InvalidArgumentException('Wechselrichter-Istleistung darf nicht negativ sein.');
|
||||
}
|
||||
|
||||
$nennleistung = (float) $nennleistung;
|
||||
$istleistung = min((float) $istleistung, $nennleistung);
|
||||
$bisherigeGrenze = $letzteGrenzen[$id] ?? $nennleistung;
|
||||
if (!is_numeric($bisherigeGrenze)) {
|
||||
throw new InvalidArgumentException('Gespeicherte Wechselrichtergrenze ist ungueltig.');
|
||||
}
|
||||
$bisherigeGrenze = max(0.0, min((float) $bisherigeGrenze, $nennleistung));
|
||||
$normalisiert[] = [
|
||||
'ID' => $id,
|
||||
'Nennleistung_W' => $nennleistung,
|
||||
'Istleistung_W' => $istleistung,
|
||||
];
|
||||
$kennungen[$id] = true;
|
||||
$nennleistungGesamt += $nennleistung;
|
||||
$istleistungGesamt += $istleistung;
|
||||
$bisherigeGrenzeGesamt += $bisherigeGrenze;
|
||||
}
|
||||
|
||||
$netzabweichung = $netzleistung + $einspeisegrenze;
|
||||
$zielGesamt = $bisherigeGrenzeGesamt;
|
||||
$nachIstleistungVerteilen = false;
|
||||
if ($netzabweichung < -$toleranz) {
|
||||
$nachIstleistungVerteilen = $istleistungGesamt > 0.0;
|
||||
$wirksameAbweichung = $netzabweichung + $toleranz;
|
||||
$zielGesamt = min($bisherigeGrenzeGesamt, $istleistungGesamt) + $wirksameAbweichung;
|
||||
} elseif ($netzabweichung > $toleranz) {
|
||||
$zielGesamt = $bisherigeGrenzeGesamt + $netzabweichung - $toleranz;
|
||||
}
|
||||
$zielGesamt = max(0.0, min($zielGesamt, $nennleistungGesamt));
|
||||
|
||||
$grenzen = [];
|
||||
foreach ($normalisiert as $eintrag) {
|
||||
$anteil = $nachIstleistungVerteilen
|
||||
? $eintrag['Istleistung_W'] / $istleistungGesamt
|
||||
: $eintrag['Nennleistung_W'] / $nennleistungGesamt;
|
||||
$grenzen[$eintrag['ID']] = round(
|
||||
min($eintrag['Nennleistung_W'], $zielGesamt * $anteil),
|
||||
3
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'Netzabweichung_W' => $netzabweichung,
|
||||
'ZielGesamtleistung_W' => round($zielGesamt, 3),
|
||||
'Abregelbedarf_W' => round(max(0.0, $istleistungGesamt - $zielGesamt), 3),
|
||||
'Grenzen_W' => $grenzen,
|
||||
];
|
||||
}
|
||||
|
||||
public static function stellwert(float $grenzeW, float $nennleistungW, string $art): float
|
||||
{
|
||||
if ($nennleistungW <= 0.0 || $grenzeW < 0.0) {
|
||||
throw new InvalidArgumentException('Leistungsgrenzen sind ungueltig.');
|
||||
}
|
||||
$grenzeW = min($grenzeW, $nennleistungW);
|
||||
if ($art === 'percent') {
|
||||
return round($grenzeW / $nennleistungW * 100.0, 2);
|
||||
}
|
||||
if ($art === 'watt') {
|
||||
return round($grenzeW, 1);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Begrenzungsart muss percent oder watt sein.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user