feat: Wärmepumpenmodul integrieren
Tests / test (push) Successful in 49s

This commit is contained in:
dh
2026-09-22 14:34:23 +00:00
parent d7308663da
commit 7845c66fd8
14 changed files with 2127 additions and 51 deletions
+190
View File
@@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
namespace Belevo\EnelixEMS;
use InvalidArgumentException;
final class WaermepumpenRegler
{
public const KONTAKTART_SPERRE_ERHOEHUNG = 0;
public const KONTAKTART_SG_READY = 1;
public const RUECKMELDUNG_LEISTUNG = 0;
public const RUECKMELDUNG_BETRIEB = 1;
public const STEUERZUSTAND_NORMAL = 0;
public const STEUERZUSTAND_SPERRE = 1;
public const STEUERZUSTAND_ERHOEHUNG = 2;
/** @return array{Kontakt1: bool, Kontakt2: bool} */
public static function kontaktwerte(int $kontaktart, int $steuerzustand): array
{
self::pruefeKontaktart($kontaktart);
self::pruefeSteuerzustand($steuerzustand);
return [
'Kontakt1' => $steuerzustand === self::STEUERZUSTAND_SPERRE,
'Kontakt2' => $steuerzustand === self::STEUERZUSTAND_ERHOEHUNG,
];
}
/** @param bool|int|float $rueckmeldung */
public static function laeuft($rueckmeldung, int $rueckmeldungsart, float $laufschwelle): bool
{
self::pruefeRueckmeldungsart($rueckmeldungsart);
if ($laufschwelle < 0) {
throw new InvalidArgumentException('Die Laufschwelle darf nicht negativ sein.');
}
if ($rueckmeldungsart === self::RUECKMELDUNG_BETRIEB) {
return (bool) $rueckmeldung;
}
return abs((float) $rueckmeldung) >= $laufschwelle;
}
/** @param bool|int|float $rueckmeldung */
public static function istleistung(
$rueckmeldung,
int $rueckmeldungsart,
int $nennleistung
): float {
self::pruefeRueckmeldungsart($rueckmeldungsart);
self::pruefeNennleistung($nennleistung);
if ($rueckmeldungsart === self::RUECKMELDUNG_BETRIEB) {
return (bool) $rueckmeldung ? (float) $nennleistung : 0.0;
}
return max(0.0, (float) $rueckmeldung);
}
/** @return list<int> */
public static function leistungsangebot(
int $nennleistung,
string $betriebsart,
bool $laeuft,
bool $verfuegbar,
bool $mindestlaufzeitAktiv,
bool $mindestsperrzeitAktiv,
bool $sperrenZulaessig,
bool $startenZulaessig,
bool $sperrerholung
): array {
self::pruefeNennleistung($nennleistung);
if (!in_array($betriebsart, [
Nachrichtenvertrag::BETRIEBSART_PV,
Nachrichtenvertrag::BETRIEBSART_PEAK,
], true)) {
throw new InvalidArgumentException('Die Betriebsart ist ungueltig.');
}
if (!$verfuegbar) {
return [$laeuft ? $nennleistung : 0];
}
if ($sperrerholung || $mindestlaufzeitAktiv) {
return [$laeuft ? $nennleistung : 0];
}
if ($betriebsart === Nachrichtenvertrag::BETRIEBSART_PV) {
return ($laeuft || (!$mindestsperrzeitAktiv && $startenZulaessig))
? [0, $nennleistung]
: [0];
}
return ($laeuft && $sperrenZulaessig)
? [0, $nennleistung]
: [$laeuft ? $nennleistung : 0];
}
public static function restzeit(int $beginn, int $dauer, int $jetzt): int
{
if ($beginn < 0 || $dauer < 0 || $jetzt < 0) {
throw new InvalidArgumentException('Zeitwerte duerfen nicht negativ sein.');
}
if ($beginn === 0 || $dauer === 0) {
return 0;
}
return max(0, $beginn + $dauer - $jetzt);
}
/**
* @param list<array{Von: int, Bis: int}> $historie
* @return list<array{Von: int, Bis: int}>
*/
public static function bereinigeSperrhistorie(array $historie, int $jetzt): array
{
if ($jetzt < 0) {
throw new InvalidArgumentException('Der Zeitpunkt darf nicht negativ sein.');
}
$grenze = $jetzt - 86400;
$ergebnis = [];
foreach ($historie as $intervall) {
$von = (int) ($intervall['Von'] ?? -1);
$bis = (int) ($intervall['Bis'] ?? -1);
if ($von < 0 || $bis < $von || $bis <= $grenze) {
continue;
}
$ergebnis[] = ['Von' => max($von, $grenze), 'Bis' => min($bis, $jetzt)];
}
return $ergebnis;
}
/** @param list<array{Von: int, Bis: int}> $historie */
public static function sperrsekunden24h(
array $historie,
int $jetzt,
?int $aktiverBeginn = null
): int {
$sekunden = 0;
foreach (self::bereinigeSperrhistorie($historie, $jetzt) as $intervall) {
$sekunden += $intervall['Bis'] - $intervall['Von'];
}
if ($aktiverBeginn !== null && $aktiverBeginn > 0) {
$sekunden += max(0, $jetzt - max($aktiverBeginn, $jetzt - 86400));
}
return min(86400, $sekunden);
}
private static function pruefeKontaktart(int $kontaktart): void
{
if (!in_array($kontaktart, [
self::KONTAKTART_SPERRE_ERHOEHUNG,
self::KONTAKTART_SG_READY,
], true)) {
throw new InvalidArgumentException('Die Kontaktart ist ungueltig.');
}
}
private static function pruefeRueckmeldungsart(int $rueckmeldungsart): void
{
if (!in_array($rueckmeldungsart, [
self::RUECKMELDUNG_LEISTUNG,
self::RUECKMELDUNG_BETRIEB,
], true)) {
throw new InvalidArgumentException('Die Rueckmeldungsart ist ungueltig.');
}
}
private static function pruefeSteuerzustand(int $steuerzustand): void
{
if (!in_array($steuerzustand, [
self::STEUERZUSTAND_NORMAL,
self::STEUERZUSTAND_SPERRE,
self::STEUERZUSTAND_ERHOEHUNG,
], true)) {
throw new InvalidArgumentException('Der Steuerzustand ist ungueltig.');
}
}
private static function pruefeNennleistung(int $nennleistung): void
{
if ($nennleistung <= 0) {
throw new InvalidArgumentException('Die Nennleistung muss groesser als 0 sein.');
}
}
}