$reserve + $hysterese) { return false; } if ($ladezustand <= $reserve) { return true; } return $bisherAktiv; } /** * Bildet das zustands- und betriebsartabhaengige Angebot als * durchgaengige Leistungsbereiche in ganzen Watt ab. * * @return list */ public static function leistungsangebot( bool $aktiv, bool $enelixSteuert, bool $peakbetrieb, float $ladezustand, float $reserve, float $minimum, bool $hystereseAktiv, float $netzleistungW, float $istleistungW, float $maxLadenW, float $maxEntladenW ): array { self::pruefeLadezustandsgrenzen($reserve, 0.0); if ($minimum < 0.0 || $minimum > 100.0 || $minimum > $reserve) { throw new InvalidArgumentException( 'Mindestladezustand muss zwischen 0 und der Reserve liegen.' ); } self::pruefeLeistungsgrenzen($maxLadenW, $maxEntladenW); if (!$aktiv || !$enelixSteuert) { return [0]; } $maxLaden = (int) floor($maxLadenW); $maxEntladen = (int) floor($maxEntladenW); if ($peakbetrieb) { if ($ladezustand > $reserve && !$hystereseAktiv) { $ziel = $netzleistungW > 0.0 ? -min($netzleistungW, $maxEntladenW) + $istleistungW : $netzleistungW; return [self::begrenzeLeistung($ziel, $maxLadenW, $maxEntladenW)]; } if ($ladezustand > $reserve && $hystereseAktiv) { return self::leistungsbereich(-$maxEntladen, 0); } if ($ladezustand > $minimum) { return self::leistungsbereich(-$maxEntladen, $maxLaden); } return self::leistungsbereich(0, $maxLaden); } if ($ladezustand > 99.0) { return self::leistungsbereich(-$maxEntladen, 0); } if ($ladezustand > $reserve && !$hystereseAktiv) { return self::leistungsbereich(-$maxEntladen, $maxLaden); } if ($ladezustand >= $reserve && $hystereseAktiv) { return self::leistungsbereich(0, $maxLaden); } return [$maxLaden]; } /** * Liefert nur die Registerwerte, die der gewaehlte Batterietyp benoetigt. * * @return array */ public static function registerwerte( int $batterietyp, int $steuerung, int $sollleistungW ): array { self::pruefeBatterietyp($batterietyp); self::pruefeSteuerung($steuerung); $management = self::managementCode($batterietyp, $steuerung); if ($steuerung === self::STEUERUNG_WECHSELRICHTER) { if ($batterietyp === self::TYP_GOODWE) { return ['Leistung' => 0, 'Management' => $management]; } return [ 'Ladeleistung' => 0, 'Entladeleistung' => 0, 'Management' => $management, ]; } $betrag = abs($sollleistungW); if ($batterietyp === self::TYP_HERSTELLERUNABHAENGIG) { return [ 'Ladeleistung' => $sollleistungW >= 0 ? $betrag : 0, 'Entladeleistung' => $sollleistungW < 0 ? $betrag : 0, 'Modus' => $sollleistungW >= 0 ? 0 : 1, 'Management' => $management, ]; } if ($batterietyp === self::TYP_GOODWE) { return [ 'Leistung' => $betrag, 'Modus' => $sollleistungW >= 0 ? 11 : 12, 'Management' => $management, ]; } if ($batterietyp === self::TYP_SOLAREDGE) { return [ 'Ladeleistung' => $sollleistungW >= 0 ? $betrag : 0, 'Entladeleistung' => $sollleistungW < 0 ? $betrag : 0, 'Modus' => $sollleistungW >= 0 ? 3 : 4, 'Management' => $management, ]; } return [ 'Ladeleistung' => $sollleistungW >= 0 ? $betrag / 1000.0 : 0.0, 'Entladeleistung' => $sollleistungW < 0 ? $betrag / 1000.0 : 0.0, 'Modus' => $sollleistungW >= 0 ? 3 : 6, 'Management' => $management, ]; } /** @return list */ public static function erforderlicheRegister(int $batterietyp): array { self::pruefeBatterietyp($batterietyp); if ($batterietyp === self::TYP_GOODWE) { return ['Management', 'Modus', 'Leistung']; } return ['Management', 'Modus', 'Ladeleistung', 'Entladeleistung']; } private static function managementCode(int $batterietyp, int $steuerung): int { if ($steuerung === self::STEUERUNG_WECHSELRICHTER) { return in_array( $batterietyp, [self::TYP_GOODWE, self::TYP_SOLAREDGE], true ) ? 1 : 0; } if ($batterietyp === self::TYP_SOLAREDGE) { return 4; } if ($batterietyp === self::TYP_GOODWE) { return 2; } return 1; } /** @return list */ private static function leistungsbereich(int $vonW, int $bisW): array { if ($vonW === $bisW) { return [$vonW]; } return [['Von_W' => $vonW, 'Bis_W' => $bisW]]; } private static function begrenzeLeistung( float $leistungW, float $maxLadenW, float $maxEntladenW ): int { $maxLaden = (int) floor($maxLadenW); $maxEntladen = (int) floor($maxEntladenW); return (int) round(min($maxLaden, max(-$maxEntladen, $leistungW))); } private static function pruefeLeistungsgrenzen(float $maxLadenW, float $maxEntladenW): void { if ($maxLadenW < 0.0 || $maxEntladenW < 0.0) { throw new InvalidArgumentException('Leistungsgrenzen duerfen nicht negativ sein.'); } } private static function pruefeLadezustandsgrenzen(float $reserve, float $hysterese): void { if ($reserve < 0.0 || $reserve > 100.0) { throw new InvalidArgumentException('Reserve muss zwischen 0 und 100 Prozent liegen.'); } if ($hysterese < 0.0 || $reserve + $hysterese > 100.0) { throw new InvalidArgumentException( 'Hysterese muss positiv sein und mit der Reserve hoechstens 100 Prozent ergeben.' ); } } private static function pruefeBatterietyp(int $batterietyp): void { if (!in_array($batterietyp, [ self::TYP_HERSTELLERUNABHAENGIG, self::TYP_GOODWE, self::TYP_SOLAREDGE, self::TYP_SIGENERGY, ], true)) { throw new InvalidArgumentException('Batterietyp ist nicht konfiguriert.'); } } private static function pruefeSteuerung(int $steuerung): void { if (!in_array($steuerung, [ self::STEUERUNG_WECHSELRICHTER, self::STEUERUNG_ENELIX, ], true)) { throw new InvalidArgumentException('Batteriesteuerung ist ungueltig.'); } } }