191 lines
5.9 KiB
PHP
191 lines
5.9 KiB
PHP
<?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.');
|
|
}
|
|
}
|
|
}
|