Files
Enelix-EMS/tests/ManagerReglerTest.php
T
2026-09-29 17:23:25 +00:00

407 lines
13 KiB
PHP

<?php
declare(strict_types=1);
namespace Belevo\EnelixEMS\Tests;
use Belevo\EnelixEMS\ManagerRegler;
use Belevo\EnelixEMS\Nachrichtenvertrag;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
final class ManagerReglerTest extends TestCase
{
public function testOhnePeakBegrenzungBleibtSolarladenAktiv(): void
{
self::assertSame(
ManagerRegler::BETRIEBSART_PV,
ManagerRegler::bestimmeBetriebsart(
true,
true,
25000.0,
ManagerRegler::BETRIEBSART_INAKTIV,
false,
0.0,
15000.0,
0.0
)
);
}
public function testBetriebsartBleibtZwischenDenZielwertenErhalten(): void
{
self::assertSame(
ManagerRegler::BETRIEBSART_PEAK,
ManagerRegler::bestimmeBetriebsart(
true,
true,
5000.0,
ManagerRegler::BETRIEBSART_PEAK,
true,
0.0,
12000.0,
0.0
)
);
}
public function testUmschaltdifferenzVerhindertZuKleineAenderung(): void
{
self::assertSame(
ManagerRegler::BETRIEBSART_PV,
ManagerRegler::bestimmeBetriebsart(
true,
true,
11000.0,
ManagerRegler::BETRIEBSART_PV,
true,
10000.0,
10500.0,
60.0
)
);
}
public function testWechseltOberhalbDerPeakgrenzeInDenPeakbetrieb(): void
{
self::assertSame(
ManagerRegler::BETRIEBSART_PEAK,
ManagerRegler::bestimmeBetriebsart(
true,
true,
12500.0,
ManagerRegler::BETRIEBSART_PV,
true,
0.0,
12000.0,
5.0
)
);
}
public function testWechseltUnterhalbDesSolarsollwertsInDenPvBetrieb(): void
{
self::assertSame(
ManagerRegler::BETRIEBSART_PV,
ManagerRegler::bestimmeBetriebsart(
true,
true,
-500.0,
ManagerRegler::BETRIEBSART_PEAK,
true,
0.0,
12000.0,
5.0
)
);
}
public function testVerteilungBeruecksichtigtPrioritaetEinzelwerteUndBereiche(): void
{
$ergebnis = ManagerRegler::verteile(
0.0,
4500.0,
[
$this->verbraucher(20, 5, [0, 3000], 0),
$this->verbraucher(10, 0, [0, ['Von_W' => 1000, 'Bis_W' => 2000], 4000], 0),
],
'PrioritaetPV'
);
self::assertSame(4500, $ergebnis['Verteilbudget_W']);
self::assertSame([10 => 4000, 20 => 0], $ergebnis['Sollwerte']);
self::assertSame(500, $ergebnis['Restabweichung_W']);
}
public function testGleichePrioritaetBevorzugtWieEnelix1DenVerbraucherMitWenigerEnergie(): void
{
$ergebnis = ManagerRegler::verteile(
0.0,
3000.0,
[
$this->verbraucher(10, 0, [0, 3000], 0),
$this->verbraucher(20, 0, [0, 3000], 0),
],
'PrioritaetPV',
[10 => 3000.0, 20 => 0.0]
);
self::assertSame([20 => 3000, 10 => 0], $ergebnis['Sollwerte']);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testEnergievergleichVerwendetWieEnelix1ZweiKilowattstundenGruppen(): void
{
$ergebnis = ManagerRegler::verteile(
0.0,
3000.0,
[
$this->verbraucher(10, 0, [0, 3000], 0),
$this->verbraucher(20, 0, [0, 3000], 0),
],
'PrioritaetPV',
[10 => 999.0, 20 => 0.0]
);
self::assertSame([10 => 3000, 20 => 0], $ergebnis['Sollwerte']);
}
public function testFestwertWirdUnabhaengigVonAenderungMoeglichZugewiesen(): void
{
$fest = $this->verbraucher(10, 0, [3000], 3000, false);
$steuerbar = $this->verbraucher(20, 1, [0, ['Von_W' => 1, 'Bis_W' => 4000]], 0);
$ergebnis = ManagerRegler::verteile(3000.0, 5000.0, [$fest, $steuerbar], 'PrioritaetPV');
self::assertSame(3000, $ergebnis['NichtSteuerbar_W']);
self::assertSame([10 => 3000, 20 => 2000], $ergebnis['Sollwerte']);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testFestwerteWerdenNachIstleistungBilanziertUndAlsBefehlBeibehalten(): void
{
$ergebnis = ManagerRegler::verteile(
-2411.0,
0.0,
[
$this->verbraucher(
44234,
0,
[['Von_W' => -39000, 'Bis_W' => 39000]],
0
),
$this->verbraucher(38676, 1, [0, 4600], 0),
$this->verbraucher(29743, 1, [0, 6500], 0),
$this->verbraucher(43878, 2, [13850], 10151, false),
$this->verbraucher(46052, 2, [11000], 0, false),
],
'PrioritaetPV'
);
self::assertSame(12562, $ergebnis['Verteilbudget_W']);
self::assertSame(10151, $ergebnis['NichtSteuerbar_W']);
self::assertSame(
[
44234 => 2411,
29743 => 0,
38676 => 0,
43878 => 13850,
46052 => 11000,
],
$ergebnis['Sollwerte']
);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testBatterieGleichtGemesseneFesteLastenAusOhneSolarladungZuSpeisen(): void
{
$ergebnis = ManagerRegler::verteile(
-4526.0,
-50.0,
[
$this->verbraucher(29743, 1, [0, 6500], 6500),
$this->verbraucher(38676, 1, [0, 4600], 4600),
$this->verbraucher(22078, 2, [7690], 0, false),
$this->verbraucher(31986, 2, [11000], 10942, false),
$this->verbraucher(43878, 2, [0, 4150, 10300], 9908),
$this->verbraucher(
44234,
6,
[['Von_W' => -39000, 'Bis_W' => 39000]],
-22769
),
],
'PrioritaetPV'
);
self::assertSame(13657, $ergebnis['Verteilbudget_W']);
self::assertSame(10942, $ergebnis['NichtSteuerbar_W']);
self::assertSame(
[
29743 => 0,
38676 => 0,
22078 => 7690,
31986 => 11000,
43878 => 0,
44234 => 2715,
],
$ergebnis['Sollwerte']
);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testBegrenztesFahrzeugLaedtVorBatterieOhneBatterieentladung(): void
{
$ergebnis = ManagerRegler::verteile(
-3587.0,
0.0,
[
$this->verbraucher(
10,
0,
[0, 4150, 4850, 5550, 6250, 6950, 7600, 8300, 9000, 9700, 10300, 11000],
10263
),
$this->verbraucher(
20,
1,
[['Von_W' => -39000, 'Bis_W' => 39000]],
0
),
],
'PrioritaetPV'
);
self::assertSame(13850, $ergebnis['Verteilbudget_W']);
self::assertSame([10 => 11000, 20 => 2850], $ergebnis['Sollwerte']);
self::assertGreaterThanOrEqual(0, $ergebnis['Sollwerte'][20]);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testPvBetriebNutztBeiPositivemBudgetKeineNegativeLeistungsstufe(): void
{
$ergebnis = ManagerRegler::verteile(
0.0,
500.0,
[
$this->verbraucher(10, 0, [-1000, 5000], 0),
$this->verbraucher(20, 1, [0, 3000], 0),
],
'PrioritaetPV'
);
self::assertSame(500, $ergebnis['Verteilbudget_W']);
self::assertSame([10 => 5000, 20 => 0], $ergebnis['Sollwerte']);
self::assertGreaterThanOrEqual(0, $ergebnis['Sollwerte'][10]);
self::assertSame(-4500, $ergebnis['Restabweichung_W']);
}
public function testPvBetriebNutztNegativeLeistungErstBeiTatsaechlichemDefizit(): void
{
$ergebnis = ManagerRegler::verteile(
1000.0,
0.0,
[
$this->verbraucher(
10,
0,
[['Von_W' => -5000, 'Bis_W' => 5000]],
0
),
$this->verbraucher(20, 1, [0, 3000], 0),
],
'PrioritaetPV'
);
self::assertSame(-1000, $ergebnis['Verteilbudget_W']);
self::assertSame([10 => -1000, 20 => 0], $ergebnis['Sollwerte']);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testFestgehaltenerVerbraucherBilanziertIstUndBehaeltSollwert(): void
{
$festgehalten = $this->verbraucher(10, 0, [0, 3000, 5000], 2000, false);
$festgehalten['Daten']['Zustand'][0]['Wert'] = 3000;
$ergebnis = ManagerRegler::verteile(
0.0,
3000.0,
[
$festgehalten,
$this->verbraucher(20, 1, [['Von_W' => 0, 'Bis_W' => 5000]], 0),
],
'PrioritaetPV'
);
self::assertSame(5000, $ergebnis['Verteilbudget_W']);
self::assertSame(2000, $ergebnis['NichtSteuerbar_W']);
self::assertSame([10 => 3000, 20 => 3000], $ergebnis['Sollwerte']);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testFehlendeIstleistungFaelltAufAngenommenenSollwertZurueck(): void
{
$verbraucher = $this->verbraucher(10, 0, [3000], null, false);
$verbraucher['Daten']['Leistungsquelle'] = Nachrichtenvertrag::LEISTUNGSQUELLE_NICHT_VORHANDEN;
$verbraucher['Daten']['Istleistung_W'] = null;
$verbraucher['Daten']['Zustand'][0]['Wert'] = 3000;
$ergebnis = ManagerRegler::verteile(3000.0, 0.0, [$verbraucher], 'PrioritaetPV');
self::assertSame(3000, $ergebnis['AktuelleVerbraucherleistung_W']);
self::assertSame([10 => 3000], $ergebnis['Sollwerte']);
self::assertSame(-3000, $ergebnis['Restabweichung_W']);
}
public function testExpliziterBatteriefahrplanBleibtVonAnderenVerbrauchernUnveraendert(): void
{
$ergebnis = ManagerRegler::verteile(
0.0,
1000.0,
[
$this->verbraucher(
10,
0,
[['Von_W' => -5000, 'Bis_W' => 5000]],
0
),
$this->verbraucher(20, 1, [0, 3000], 0),
],
'PrioritaetPV',
[],
[10 => 1000]
);
self::assertSame([10 => 1000, 20 => 0], $ergebnis['Sollwerte']);
self::assertSame(0, $ergebnis['Restabweichung_W']);
}
public function testMonatlicheGrenzeMussVollstaendigSein(): void
{
$this->expectException(InvalidArgumentException::class);
ManagerRegler::wirksameLastspitzengrenze(2, 0.0, [1 => 12000.0], 9);
}
/**
* @param list<int|array{Von_W: int, Bis_W: int}> $leistungswerte
* @return array{InstanzID: int, Daten: array<string, mixed>}
*/
private function verbraucher(
int $instanzID,
int $prioritaet,
array $leistungswerte,
?int $istleistung,
bool $aenderungMoeglich = true
): array {
$quelle = $istleistung === null
? Nachrichtenvertrag::LEISTUNGSQUELLE_NICHT_VORHANDEN
: Nachrichtenvertrag::LEISTUNGSQUELLE_GEMESSEN;
return [
'InstanzID' => $instanzID,
'Daten' => [
'Kopf' => [
'Version' => Nachrichtenvertrag::VERSION,
'AbsenderID' => $instanzID,
'EmpfaengerID' => 1,
'Zeitpunkt' => 1788825600,
],
'Betriebsart' => Nachrichtenvertrag::BETRIEBSART_PV,
'PrioritaetPV' => $prioritaet,
'PrioritaetPeak' => $prioritaet,
'Leistungswerte_W' => $leistungswerte,
'AenderungMoeglich' => $aenderungMoeglich,
'Verfuegbar' => true,
'Istleistung_W' => $istleistung,
'Leistungsquelle' => $quelle,
'Zustand' => [[
'Kennung' => 'Sollleistung_W',
'Art' => 'Sollwert',
'Wert' => $istleistung,
'Einheit' => 'W',
]],
],
];
}
}