This commit is contained in:
@@ -62,7 +62,7 @@ final class DemoanlageBootstrapTest extends TestCase
|
||||
self::assertSame([
|
||||
'VariableConfigType' => 0,
|
||||
'VariableID' => 12345,
|
||||
'SecondaryVariableID' => 0,
|
||||
'SecondaryVariableID' => 1,
|
||||
'Name' => 'PV-Anlage',
|
||||
'Type' => 'solar',
|
||||
'Grouped' => false,
|
||||
@@ -70,6 +70,69 @@ final class DemoanlageBootstrapTest extends TestCase
|
||||
'InfoVariableID' => 54321,
|
||||
'Invert' => false,
|
||||
], enelixDemoEnergyNode(12345, 'PV-Anlage', 'solar', 54321));
|
||||
self::assertSame(
|
||||
1,
|
||||
enelixDemoEnergyNode(12345, 'PV-Anlage', 'solar')['InfoVariableID']
|
||||
);
|
||||
}
|
||||
|
||||
public function testNativeDiagrammDatenreiheHatSymconFormat(): void
|
||||
{
|
||||
self::assertSame([
|
||||
'variableID' => 12345,
|
||||
'fillColor' => 'clear',
|
||||
'strokeColor' => '#f4c542',
|
||||
'timeOffset' => 0,
|
||||
'visible' => true,
|
||||
'title' => 'PV',
|
||||
'type' => 'line',
|
||||
'side' => 'left',
|
||||
'profile' => '~Power',
|
||||
], enelixDemoChartDataset(12345, 'PV', '#f4c542', '~Power'));
|
||||
}
|
||||
|
||||
public function testDashboardVerwendetNativeEnergieverteilungUndNeueBoilerlisten(): void
|
||||
{
|
||||
$source = file_get_contents(dirname(__DIR__) . '/examples/Demoanlage/bootstrap.php');
|
||||
|
||||
self::assertIsString($source);
|
||||
self::assertStringContainsString("IPS_SetHidden(\$legacyFlow, true);", $source);
|
||||
self::assertStringContainsString("'EnergieverteilungNativ'", $source);
|
||||
self::assertStringContainsString(
|
||||
'enelixDemoConfigureVisualization($root, $energyDistribution);',
|
||||
$source
|
||||
);
|
||||
self::assertStringContainsString('ENELIX_DEMO_DUMMY_MODULE', $source);
|
||||
self::assertStringContainsString("'Boiler1Liste'", $source);
|
||||
self::assertStringContainsString("'Boiler2Liste'", $source);
|
||||
self::assertStringContainsString("'EnergieflussPVkW'", $source);
|
||||
self::assertStringContainsString("'~Power'", $source);
|
||||
self::assertStringContainsString("'~Electricity'", $source);
|
||||
self::assertStringContainsString(
|
||||
"enelixDemoEnergyNode(\$flowPv, 'PV-Anlage', 'solar')",
|
||||
$source
|
||||
);
|
||||
self::assertStringContainsString(
|
||||
"enelixDemoEnergyNode(\$flowBase, 'Haus-Grundlast', 'consumer')",
|
||||
$source
|
||||
);
|
||||
self::assertStringContainsString(
|
||||
"enelixDemoEnergyNode(\$flowDryer, 'Entfeuchter', 'consumer')",
|
||||
$source
|
||||
);
|
||||
self::assertStringContainsString(
|
||||
"enelixDemoEnsureChart(\$history, 'LeistungsdiagrammNativ'",
|
||||
$source
|
||||
);
|
||||
self::assertStringContainsString('IPS_SetHidden($powerChart, true);', $source);
|
||||
self::assertStringContainsString(
|
||||
"enelixDemoLinkInstanceVariables(\$boiler1List, \$boiler1, \$temp1);",
|
||||
$source
|
||||
);
|
||||
self::assertStringContainsString(
|
||||
"foreach (['Boiler1Link', 'Boiler2Link'] as \$oldLinkIdent)",
|
||||
$source
|
||||
);
|
||||
}
|
||||
|
||||
public function testRollbackIstExplizitBestaetigungspflichtig(): void
|
||||
|
||||
@@ -13,9 +13,7 @@ final class DokumentationsstrukturTest extends TestCase
|
||||
{
|
||||
return [
|
||||
['Batterie'],
|
||||
['Pufferspeicher'],
|
||||
['Waermepumpe'],
|
||||
['Ladestation-Stand-Alone'],
|
||||
['Ladestation-Gateway'],
|
||||
['Easee-Gateway'],
|
||||
];
|
||||
@@ -33,6 +31,23 @@ final class DokumentationsstrukturTest extends TestCase
|
||||
self::assertStringContainsString('Properties', $inhalt);
|
||||
}
|
||||
|
||||
public function testPufferspeicherDokumentiertDenImplementiertenStand(): void
|
||||
{
|
||||
$inhalt = file_get_contents(__DIR__ . '/../docs/module/Pufferspeicher/README.md');
|
||||
self::assertNotFalse($inhalt);
|
||||
self::assertStringContainsString('Status: implementiert', $inhalt);
|
||||
self::assertStringContainsString('Managerkommunikation', $inhalt);
|
||||
}
|
||||
|
||||
public function testLadestationStandAloneDokumentiertDenImplementiertenStand(): void
|
||||
{
|
||||
$inhalt = file_get_contents(__DIR__ . '/../docs/module/Ladestation-Stand-Alone/README.md');
|
||||
self::assertNotFalse($inhalt);
|
||||
self::assertStringContainsString('Status: Implementiert', $inhalt);
|
||||
self::assertStringContainsString('Properties', $inhalt);
|
||||
self::assertStringContainsString('Fake-HTTP-Transport', $inhalt);
|
||||
}
|
||||
|
||||
public function testSchnittstellenDokumentiertSind(): void
|
||||
{
|
||||
self::assertFileExists(__DIR__ . '/../docs/Schnittstelle.md');
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixEMS\Tests;
|
||||
|
||||
use Belevo\EnelixEMS\LadestationAdapter;
|
||||
use Belevo\EnelixEMS\LadestationTransport;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LadestationAdapterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider statusFaelle
|
||||
* @param array<string, string> $konfiguration
|
||||
* @param array{Rohstatus: int, Istleistung_W: float} $erwartet
|
||||
*/
|
||||
public function testStatusaufrufUndDekodierungFuerAlleGeraete(
|
||||
int $geraetetyp,
|
||||
array $konfiguration,
|
||||
string $antwort,
|
||||
string $erwarteteUrl,
|
||||
array $erwartet
|
||||
): void {
|
||||
$aufrufe = [];
|
||||
$transport = new LadestationTransport(static function (array $anfrage) use (
|
||||
&$aufrufe,
|
||||
$antwort
|
||||
): string {
|
||||
$aufrufe[] = $anfrage;
|
||||
return $antwort;
|
||||
});
|
||||
|
||||
$rohstatus = LadestationAdapter::dekodiereStatus(
|
||||
$geraetetyp,
|
||||
$transport->statusLesen($geraetetyp, $konfiguration)
|
||||
);
|
||||
|
||||
self::assertSame($erwarteteUrl, $aufrufe[0]['URL']);
|
||||
self::assertSame('GET', $aufrufe[0]['Methode']);
|
||||
self::assertSame($erwartet, $rohstatus);
|
||||
}
|
||||
|
||||
/** @return iterable<string, array<mixed>> */
|
||||
public function statusFaelle(): iterable
|
||||
{
|
||||
yield 'go-e alt' => [
|
||||
LadestationAdapter::GO_E_ALT,
|
||||
$this->lokaleKonfiguration(),
|
||||
$this->goEAntwort(2, 1100),
|
||||
'http://192.0.2.10/mqtt?payload=',
|
||||
['Rohstatus' => 2, 'Istleistung_W' => 11000.0],
|
||||
];
|
||||
yield 'go-e Gemini' => [
|
||||
LadestationAdapter::GO_E_GEMINI,
|
||||
$this->lokaleKonfiguration(),
|
||||
$this->goEAntwort(2, 2300),
|
||||
'http://192.0.2.10/api/status',
|
||||
['Rohstatus' => 2, 'Istleistung_W' => 2300.0],
|
||||
];
|
||||
yield 'Smart-me Pico' => [
|
||||
LadestationAdapter::SMART_ME_PICO,
|
||||
$this->picoKonfiguration(),
|
||||
json_encode([
|
||||
'State' => 2,
|
||||
'ActiveChargingPower' => 11.0,
|
||||
'MaxAllowedChargingCurrent' => 16,
|
||||
], JSON_THROW_ON_ERROR),
|
||||
'https://api.smart-me.com/pico/charging/pico-id',
|
||||
['Rohstatus' => 2, 'Istleistung_W' => 11000.0],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider steuerFaelle
|
||||
* @param array<string, string> $konfiguration
|
||||
* @param list<array{Methode: string, URL: string}> $erwarteteAufrufe
|
||||
*/
|
||||
public function testSteueraufrufeWerdenUeberFakeTransportGeprueft(
|
||||
int $geraetetyp,
|
||||
array $konfiguration,
|
||||
int $strom,
|
||||
array $erwarteteAufrufe
|
||||
): void {
|
||||
$aufrufe = [];
|
||||
$transport = new LadestationTransport(static function (array $anfrage) use (&$aufrufe): string {
|
||||
unset($anfrage['Benutzername'], $anfrage['Passwort']);
|
||||
$aufrufe[] = $anfrage;
|
||||
return '{}';
|
||||
});
|
||||
|
||||
$transport->ladestromSetzen($geraetetyp, $konfiguration, $strom);
|
||||
|
||||
self::assertSame($erwarteteAufrufe, $aufrufe);
|
||||
}
|
||||
|
||||
/** @return iterable<string, array<mixed>> */
|
||||
public function steuerFaelle(): iterable
|
||||
{
|
||||
yield 'go-e alt laden' => [
|
||||
LadestationAdapter::GO_E_ALT,
|
||||
$this->lokaleKonfiguration(),
|
||||
16,
|
||||
[
|
||||
['Methode' => 'GET', 'URL' => 'http://192.0.2.10/mqtt?payload=alw=1'],
|
||||
['Methode' => 'GET', 'URL' => 'http://192.0.2.10/mqtt?payload=amp=16'],
|
||||
],
|
||||
];
|
||||
yield 'go-e Gemini stoppen' => [
|
||||
LadestationAdapter::GO_E_GEMINI,
|
||||
$this->lokaleKonfiguration(),
|
||||
0,
|
||||
[[
|
||||
'Methode' => 'GET',
|
||||
'URL' => 'http://192.0.2.10/api/set?frc=1&sua=false',
|
||||
]],
|
||||
];
|
||||
yield 'Smart-me Pico laden' => [
|
||||
LadestationAdapter::SMART_ME_PICO,
|
||||
$this->picoKonfiguration(),
|
||||
16,
|
||||
[[
|
||||
'Methode' => 'POST',
|
||||
'URL' => 'https://api.smart-me.com/pico/loadmanagementgroup/current/serial-1?current=16000',
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
||||
public function testPicoAnfragenVerwendenBasicAuth(): void
|
||||
{
|
||||
$anfrage = LadestationAdapter::statusAnfrage(
|
||||
LadestationAdapter::SMART_ME_PICO,
|
||||
$this->picoKonfiguration()
|
||||
);
|
||||
|
||||
self::assertSame('api-user', $anfrage['Benutzername']);
|
||||
self::assertSame(hash('sha256', __FILE__), $anfrage['Passwort']);
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
private function lokaleKonfiguration(): array
|
||||
{
|
||||
return [
|
||||
'Geraeteadresse' => '192.0.2.10',
|
||||
'GeraeteID' => '',
|
||||
'Seriennummer' => '',
|
||||
'Benutzername' => '',
|
||||
'Passwort' => '',
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
private function picoKonfiguration(): array
|
||||
{
|
||||
return [
|
||||
'Geraeteadresse' => '',
|
||||
'GeraeteID' => 'pico-id',
|
||||
'Seriennummer' => 'serial-1',
|
||||
'Benutzername' => 'api-user',
|
||||
'Passwort' => hash('sha256', __FILE__),
|
||||
];
|
||||
}
|
||||
|
||||
private function goEAntwort(int $status, float $leistung): string
|
||||
{
|
||||
$nrg = array_fill(0, 12, 0);
|
||||
$nrg[11] = $leistung;
|
||||
|
||||
return json_encode(['car' => $status, 'nrg' => $nrg], JSON_THROW_ON_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixEMS\Tests;
|
||||
|
||||
use Belevo\EnelixEMS\LadestationRegler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LadestationReglerTest extends TestCase
|
||||
{
|
||||
public function testFahrzeugUndDreiPhasenWerdenWieInEnelixEinsErkannt(): void
|
||||
{
|
||||
$status = LadestationRegler::normalisiereStatus([
|
||||
'Rohstatus' => 2,
|
||||
'Istleistung_W' => 11000.0,
|
||||
], false);
|
||||
|
||||
self::assertTrue($status['FahrzeugVerbunden']);
|
||||
self::assertFalse($status['FahrzeugGeladen']);
|
||||
self::assertSame(3, $status['Fahrzeugstatus']);
|
||||
self::assertSame(LadestationRegler::PHASEN_DREI, $status['Phasenzahl']);
|
||||
}
|
||||
|
||||
public function testEinphasigesFahrzeugWirdUnterhalb7500WErkannt(): void
|
||||
{
|
||||
$status = LadestationRegler::normalisiereStatus([
|
||||
'Rohstatus' => 2,
|
||||
'Istleistung_W' => 2300.0,
|
||||
], false);
|
||||
|
||||
self::assertSame(LadestationRegler::PHASEN_EIN, $status['Phasenzahl']);
|
||||
self::assertEqualsWithDelta(10.0, $status['Ladestrom_A'], 0.01);
|
||||
}
|
||||
|
||||
public function testGeladenWirdNachVerbindungUnterSechsAmpereErkannt(): void
|
||||
{
|
||||
$status = LadestationRegler::normalisiereStatus([
|
||||
'Rohstatus' => 2,
|
||||
'Istleistung_W' => 0.0,
|
||||
], true);
|
||||
|
||||
self::assertTrue($status['FahrzeugGeladen']);
|
||||
self::assertSame(4, $status['Fahrzeugstatus']);
|
||||
}
|
||||
|
||||
public function testBetriebsartUndSolarladenBestimmenDasLeistungsangebot(): void
|
||||
{
|
||||
$solarPV = LadestationRegler::leistungsangebot(true, true, true, false, 1, 16, true, false);
|
||||
$normalPV = LadestationRegler::leistungsangebot(true, true, true, false, 1, 16, false, false);
|
||||
$solarPeak = LadestationRegler::leistungsangebot(true, true, true, false, 1, 16, true, true);
|
||||
$normalPeak = LadestationRegler::leistungsangebot(true, true, true, false, 1, 16, false, true);
|
||||
|
||||
self::assertSame(0, $solarPV[0]);
|
||||
self::assertCount(12, $solarPV);
|
||||
self::assertSame([3850], $normalPV);
|
||||
self::assertSame([0], $solarPeak);
|
||||
self::assertSame($solarPV, $normalPeak);
|
||||
}
|
||||
|
||||
public function testPeakKannJedesFahrzeugAufNullSetzen(): void
|
||||
{
|
||||
self::assertSame(0, LadestationRegler::stromFuerLeistung(0, 3));
|
||||
self::assertSame(6, LadestationRegler::stromFuerLeistung(4150, 3));
|
||||
self::assertSame(16, LadestationRegler::stromFuerLeistung(11000, 3));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixEMS\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LadestationStandAloneModulstrukturTest extends TestCase
|
||||
{
|
||||
private const MODULPFAD = __DIR__ . '/../LadestationStandAlone/';
|
||||
|
||||
public function testModulIstVollstaendigUndMetadatenSindGueltig(): void
|
||||
{
|
||||
foreach (['module.json', 'form.json', 'module.php'] as $datei) {
|
||||
self::assertFileExists(self::MODULPFAD . $datei);
|
||||
}
|
||||
|
||||
$modul = json_decode(
|
||||
(string) file_get_contents(self::MODULPFAD . 'module.json'),
|
||||
true,
|
||||
512,
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
self::assertSame('LadestationStandAlone', $modul['name']);
|
||||
self::assertSame('8.0', json_decode(
|
||||
(string) file_get_contents(__DIR__ . '/../library.json'),
|
||||
true,
|
||||
512,
|
||||
JSON_THROW_ON_ERROR
|
||||
)['compatibility']['version']);
|
||||
}
|
||||
|
||||
public function testGemeinsamerVerbrauchervertragWirdVerwendet(): void
|
||||
{
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
|
||||
self::assertStringContainsString('implements VerbraucherSchnittstelle', $modul);
|
||||
self::assertStringContainsString('use VerbraucherBasisTrait;', $modul);
|
||||
self::assertStringContainsString('ManagerdatenEmpfangen(array $daten)', $modul);
|
||||
self::assertStringContainsString('Nachrichtenvertrag::pruefeVerbraucherdaten', $modul);
|
||||
self::assertStringNotContainsString("RegisterVariableString('PowerSteps'", $modul);
|
||||
}
|
||||
|
||||
public function testAlleDreiStandAloneGeraeteUndSichereZugangsdatenSindKonfiguriert(): void
|
||||
{
|
||||
$form = json_decode(
|
||||
(string) file_get_contents(self::MODULPFAD . 'form.json'),
|
||||
true,
|
||||
512,
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
$json = json_encode($form, JSON_THROW_ON_ERROR);
|
||||
|
||||
self::assertStringContainsString('go-e Charger (alte API)', $json);
|
||||
self::assertStringContainsString('go-e Charger Gemini', $json);
|
||||
self::assertStringContainsString('Gemini flex', $json);
|
||||
self::assertStringContainsString('smart-me Pico', $json);
|
||||
self::assertStringContainsString('PasswordTextBox', $json);
|
||||
self::assertStringNotContainsString('Testmodus', $json);
|
||||
}
|
||||
|
||||
public function testVisualisierungsbuttonsLoggingUndDiagnoseSindVorhanden(): void
|
||||
{
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
|
||||
self::assertStringContainsString("EnableAction('Ladefreigabe')", $modul);
|
||||
self::assertStringContainsString("EnableAction('Solarladen')", $modul);
|
||||
self::assertStringContainsString("ReadPropertyBoolean('LoggingEin')", $modul);
|
||||
self::assertStringContainsString("ReadPropertyBoolean('EinstellungenInVisu')", $modul);
|
||||
self::assertStringContainsString('UnregisterVariable($ident)', $modul);
|
||||
}
|
||||
}
|
||||
@@ -168,6 +168,7 @@ final class ManagerReglerTest extends TestCase
|
||||
'EmpfaengerID' => 1,
|
||||
'Zeitpunkt' => 1788825600,
|
||||
],
|
||||
'Betriebsart' => Nachrichtenvertrag::BETRIEBSART_PV,
|
||||
'PrioritaetPV' => $prioritaet,
|
||||
'PrioritaetPeak' => $prioritaet,
|
||||
'Leistungswerte_W' => $leistungswerte,
|
||||
|
||||
@@ -14,12 +14,28 @@ final class NachrichtenvertragTest extends TestCase
|
||||
{
|
||||
Nachrichtenvertrag::pruefeManagerdaten([
|
||||
'Kopf' => $this->kopf(10001, 20001),
|
||||
'Betriebsart' => Nachrichtenvertrag::BETRIEBSART_PV,
|
||||
'Sollleistung_W' => 1501,
|
||||
]);
|
||||
|
||||
Nachrichtenvertrag::pruefeManagerdaten([
|
||||
'Kopf' => $this->kopf(10001, 20001),
|
||||
'Betriebsart' => Nachrichtenvertrag::BETRIEBSART_PEAK,
|
||||
'Sollleistung_W' => null,
|
||||
]);
|
||||
|
||||
self::assertTrue(true);
|
||||
}
|
||||
|
||||
public function testUngueltigeBetriebsartWirdAbgelehnt(): void
|
||||
{
|
||||
$daten = $this->verbraucherdaten();
|
||||
$daten['Betriebsart'] = 'Unbekannt';
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
Nachrichtenvertrag::pruefeVerbraucherdaten($daten);
|
||||
}
|
||||
|
||||
public function testGueltigeVerbraucherdatenMitEinzelwertenUndBereichenWerdenAkzeptiert(): void
|
||||
{
|
||||
Nachrichtenvertrag::pruefeVerbraucherdaten($this->verbraucherdaten());
|
||||
@@ -92,6 +108,7 @@ final class NachrichtenvertragTest extends TestCase
|
||||
{
|
||||
return [
|
||||
'Kopf' => $this->kopf(20001, 10001),
|
||||
'Betriebsart' => Nachrichtenvertrag::BETRIEBSART_PEAK,
|
||||
'PrioritaetPV' => 0,
|
||||
'PrioritaetPeak' => 12,
|
||||
'Leistungswerte_W' => [
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixEMS\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class PufferspeicherModulstrukturTest extends TestCase
|
||||
{
|
||||
private const MODULPFAD = __DIR__ . '/../Pufferspeicher/';
|
||||
|
||||
public function testModulIstVollstaendigUndMetadatenSindGueltig(): void
|
||||
{
|
||||
foreach (['module.json', 'form.json', 'module.php'] as $datei) {
|
||||
self::assertFileExists(self::MODULPFAD . $datei);
|
||||
}
|
||||
$metadaten = json_decode(
|
||||
(string) file_get_contents(self::MODULPFAD . 'module.json'),
|
||||
true,
|
||||
512,
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
self::assertSame('VerbraucherPufferspeicher', $metadaten['name']);
|
||||
self::assertSame('Enelix', $metadaten['vendor']);
|
||||
self::assertSame(['Pufferspeicher'], $metadaten['aliases']);
|
||||
self::assertSame(3, $metadaten['type']);
|
||||
}
|
||||
|
||||
public function testPropertiesSindRegistriertUndInGewuenschterReihenfolgeImFormular(): void
|
||||
{
|
||||
$basis = (string) file_get_contents(__DIR__ . '/../libs/VerbraucherBasisTrait.php');
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
preg_match_all(
|
||||
'/RegisterProperty(?:Integer|Float|Boolean|String)\(\'([^\']+)\'/',
|
||||
$basis . $modul,
|
||||
$treffer
|
||||
);
|
||||
$properties = array_values(array_unique($treffer[1]));
|
||||
$formularText = (string) file_get_contents(self::MODULPFAD . 'form.json');
|
||||
foreach ($properties as $property) {
|
||||
self::assertStringContainsString('"name": "' . $property . '"', $formularText, $property);
|
||||
}
|
||||
|
||||
$formular = json_decode($formularText, true, 512, JSON_THROW_ON_ERROR);
|
||||
self::assertSame(
|
||||
[
|
||||
'Manager und Zeitverhalten',
|
||||
'Pufferspeicher',
|
||||
'Heizkurve',
|
||||
'Erweiterte Einstellungen',
|
||||
],
|
||||
array_column($formular['elements'], 'caption')
|
||||
);
|
||||
}
|
||||
|
||||
public function testModulVerwendetVertrag40UndBetriebsartabhaengigesAngebot(): void
|
||||
{
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
|
||||
self::assertStringContainsString('implements VerbraucherSchnittstelle', $modul);
|
||||
self::assertStringContainsString('ManagerdatenEmpfangen(array $daten)', $modul);
|
||||
self::assertStringContainsString("['Betriebsart']", $modul);
|
||||
self::assertStringContainsString('BETRIEBSART_PEAK', $modul);
|
||||
self::assertStringContainsString("'Betriebsart' =>", $modul);
|
||||
self::assertStringNotContainsString("RegisterVariableString('PowerSteps'", $modul);
|
||||
self::assertStringNotContainsString("RegisterPropertyInteger('ManagerID'", $modul);
|
||||
}
|
||||
|
||||
public function testEinAusLoggingVariablenUndWaermepumpenaktionSindEnthalten(): void
|
||||
{
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
$formular = (string) file_get_contents(self::MODULPFAD . 'form.json');
|
||||
|
||||
self::assertStringContainsString("case 'Aktiv':", $modul);
|
||||
self::assertStringContainsString("ReadPropertyBoolean('LoggingEin')", $modul);
|
||||
foreach ([
|
||||
'Puffertemperatur',
|
||||
'Aussentemperatur',
|
||||
'Solltemperatur',
|
||||
'Heizbedarf',
|
||||
] as $ident) {
|
||||
self::assertStringContainsString("RegisterVariable", $modul);
|
||||
self::assertStringContainsString("'" . $ident . "'", $modul);
|
||||
}
|
||||
self::assertStringContainsString('HeizkurveVonWaermepumpeUebernehmen', $modul);
|
||||
self::assertStringContainsString('Wert von Waermepumpe uebernehmen', $formular);
|
||||
}
|
||||
|
||||
public function testSchaltfolgeIstBreakBeforeMake(): void
|
||||
{
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
$aus = strpos($modul, "RequestAction(\$stufe['KontaktID'], false)");
|
||||
$ein = strpos($modul, "RequestAction(\$stufe['KontaktID'], true)");
|
||||
|
||||
self::assertIsInt($aus);
|
||||
self::assertIsInt($ein);
|
||||
self::assertLessThan($ein, $aus);
|
||||
}
|
||||
|
||||
public function testManagerKenntDieModulIDGenauEinmal(): void
|
||||
{
|
||||
$manager = (string) file_get_contents(__DIR__ . '/../Manager/module.php');
|
||||
|
||||
self::assertSame(1, substr_count(
|
||||
$manager,
|
||||
'{C92D5EEF-9632-47A5-9659-4B02BF40FBE9}'
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixEMS\Tests;
|
||||
|
||||
use Belevo\EnelixEMS\PufferspeicherRegler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class PufferspeicherReglerTest extends TestCase
|
||||
{
|
||||
/** @return list<array{Stufe: int, Leistung_W: int, KontaktID: int}> */
|
||||
private function stufen(): array
|
||||
{
|
||||
return [
|
||||
['Stufe' => 1, 'Leistung_W' => 1000, 'KontaktID' => 101],
|
||||
['Stufe' => 2, 'Leistung_W' => 2000, 'KontaktID' => 102],
|
||||
];
|
||||
}
|
||||
|
||||
public function testHeizkurveWirdBerechnetUndBegrenzt(): void
|
||||
{
|
||||
self::assertSame(
|
||||
50.0,
|
||||
PufferspeicherRegler::solltemperatur(5.0, 35.0, 1.0, 20.0, 80.0)
|
||||
);
|
||||
self::assertSame(
|
||||
80.0,
|
||||
PufferspeicherRegler::solltemperatur(-100.0, 35.0, 1.0, 20.0, 80.0)
|
||||
);
|
||||
self::assertSame(
|
||||
20.0,
|
||||
PufferspeicherRegler::solltemperatur(100.0, 35.0, 1.0, 20.0, 80.0)
|
||||
);
|
||||
}
|
||||
|
||||
public function testUnterErrechneterEinschaltschwelleWerdenAlleStufenAngeboten(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[0, 1000, 2000],
|
||||
PufferspeicherRegler::leistungsangebot(
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
44.9,
|
||||
45.0,
|
||||
$this->stufen()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testInHystereseUndDarueberWirdNurNullAngeboten(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[0],
|
||||
PufferspeicherRegler::leistungsangebot(
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
45.0,
|
||||
45.0,
|
||||
$this->stufen()
|
||||
)
|
||||
);
|
||||
self::assertSame(
|
||||
[0],
|
||||
PufferspeicherRegler::leistungsangebot(
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
51.0,
|
||||
45.0,
|
||||
$this->stufen()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testPeakbetriebBietetUnabhaengigVonDerTemperaturNurNull(): void
|
||||
{
|
||||
foreach ([-20.0, 44.9, 45.0, 100.0] as $temperatur) {
|
||||
self::assertSame(
|
||||
[0],
|
||||
PufferspeicherRegler::leistungsangebot(
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
$temperatur,
|
||||
45.0,
|
||||
$this->stufen()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAusgeschaltetWirdImmerNurNullAngeboten(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[0],
|
||||
PufferspeicherRegler::leistungsangebot(
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
-20.0,
|
||||
45.0,
|
||||
$this->stufen()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testMindesttemperaturIstOptionalStatischOderDifferenzbasiert(): void
|
||||
{
|
||||
self::assertSame(
|
||||
45.0,
|
||||
PufferspeicherRegler::einschaltschwelle(
|
||||
50.0,
|
||||
5.0,
|
||||
PufferspeicherRegler::MINIMUM_AUS,
|
||||
30.0,
|
||||
10.0
|
||||
)
|
||||
);
|
||||
self::assertSame(
|
||||
42.0,
|
||||
PufferspeicherRegler::einschaltschwelle(
|
||||
50.0,
|
||||
5.0,
|
||||
PufferspeicherRegler::MINIMUM_STATISCH,
|
||||
42.0,
|
||||
10.0
|
||||
)
|
||||
);
|
||||
self::assertSame(
|
||||
43.0,
|
||||
PufferspeicherRegler::einschaltschwelle(
|
||||
50.0,
|
||||
5.0,
|
||||
PufferspeicherRegler::MINIMUM_DIFFERENZ,
|
||||
30.0,
|
||||
7.0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testWaermepumpenwertKalibriertFusspunktAmAktuellenAussenwert(): void
|
||||
{
|
||||
$fusspunkt = PufferspeicherRegler::fusspunktAusWaermepumpenwert(50.0, 5.0, 1.0);
|
||||
|
||||
self::assertSame(35.0, $fusspunkt);
|
||||
self::assertSame(
|
||||
50.0,
|
||||
PufferspeicherRegler::solltemperatur(5.0, $fusspunkt, 1.0, 0.0, 100.0)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,17 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'LadestationStandAlone' => [
|
||||
'file' => __DIR__ . '/modules/LadestationStandAlone.php',
|
||||
'paths' => [
|
||||
'LadestationStandAlone/*',
|
||||
'libs/LadestationAdapter.php',
|
||||
'libs/LadestationRegler.php',
|
||||
'libs/VerbraucherBasisTrait.php',
|
||||
'libs/VerbraucherSchnittstelle.php',
|
||||
'libs/Nachrichtenvertrag.php',
|
||||
],
|
||||
],
|
||||
'Manager' => [
|
||||
'file' => __DIR__ . '/modules/Manager.php',
|
||||
'paths' => [
|
||||
@@ -14,6 +25,16 @@ return [
|
||||
'libs/VerbraucherSchnittstelle.php',
|
||||
],
|
||||
],
|
||||
'Pufferspeicher' => [
|
||||
'file' => __DIR__ . '/modules/Pufferspeicher.php',
|
||||
'paths' => [
|
||||
'Pufferspeicher/*',
|
||||
'libs/PufferspeicherRegler.php',
|
||||
'libs/VerbraucherBasisTrait.php',
|
||||
'libs/VerbraucherSchnittstelle.php',
|
||||
'libs/Nachrichtenvertrag.php',
|
||||
],
|
||||
],
|
||||
'VerbraucherEinStufig' => [
|
||||
'file' => __DIR__ . '/modules/VerbraucherEinStufig.php',
|
||||
'paths' => [
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Belevo\EnelixEMS\SymconTest\TestContext;
|
||||
|
||||
return static function (TestContext $test): void {
|
||||
$testPasswort = hash('sha256', __FILE__);
|
||||
$goEAntwort = static function (int $status, float $leistung): string {
|
||||
$nrg = array_fill(0, 12, 0);
|
||||
$nrg[11] = $leistung;
|
||||
return json_encode(['car' => $status, 'nrg' => $nrg], JSON_THROW_ON_ERROR);
|
||||
};
|
||||
|
||||
$definitionen = [
|
||||
'go-e alt' => [
|
||||
'Geraetetyp' => 1,
|
||||
'Geraeteadresse' => '192.0.2.10',
|
||||
'Testantwort' => $goEAntwort(2, 1100),
|
||||
'Phasenzahl' => 3,
|
||||
'BefehlUrlTeil' => 'amp=16',
|
||||
],
|
||||
'go-e Gemini' => [
|
||||
'Geraetetyp' => 2,
|
||||
'Geraeteadresse' => '192.0.2.11',
|
||||
'Testantwort' => $goEAntwort(2, 2300),
|
||||
'Phasenzahl' => 1,
|
||||
'BefehlUrlTeil' => 'amp=16',
|
||||
],
|
||||
'smart-me Pico' => [
|
||||
'Geraetetyp' => 3,
|
||||
'GeraeteID' => 'pico-id',
|
||||
'Seriennummer' => 'serial-1',
|
||||
'Benutzername' => 'api-user',
|
||||
'Passwort' => $testPasswort,
|
||||
'Testantwort' => json_encode([
|
||||
'State' => 2,
|
||||
'ActiveChargingPower' => 11.0,
|
||||
'MaxAllowedChargingCurrent' => 16,
|
||||
], JSON_THROW_ON_ERROR),
|
||||
'Phasenzahl' => 3,
|
||||
'BefehlUrlTeil' => 'current=16000',
|
||||
],
|
||||
];
|
||||
|
||||
$stationen = [];
|
||||
foreach ($definitionen as $name => $definition) {
|
||||
$properties = array_merge($definition, [
|
||||
'MaximalerLadestrom' => 16,
|
||||
'Ladefreigabe' => true,
|
||||
'Solarladen' => true,
|
||||
'EinstellungenInVisu' => true,
|
||||
'DiagnosevariablenAnzeigen' => true,
|
||||
'Testmodus' => true,
|
||||
]);
|
||||
unset($properties['Phasenzahl'], $properties['BefehlUrlTeil']);
|
||||
$stationen[$name] = $test->createInstance(
|
||||
'{0D94913C-0F31-4C29-A685-6EB4AE58E55D}',
|
||||
'Ladestation ' . $name,
|
||||
$properties
|
||||
);
|
||||
}
|
||||
|
||||
$managerId = $test->createInstance(
|
||||
'{6F771B18-59D4-4C8A-B951-3B2FE9F6A2C4}',
|
||||
'Hilfsmanager Ladestation',
|
||||
[
|
||||
'AutomatischeSuche' => false,
|
||||
'VerbraucherZuordnung' => json_encode(array_map(
|
||||
static fn (int $id): array => ['InstanzID' => $id, 'Aktiv' => true],
|
||||
array_values($stationen)
|
||||
), JSON_THROW_ON_ERROR),
|
||||
]
|
||||
);
|
||||
|
||||
$anforderungSenden = static function (
|
||||
int $stationId,
|
||||
int $leistung,
|
||||
string $betriebsart = 'PV'
|
||||
) use ($managerId): void {
|
||||
IPS_RequestAction($stationId, 'ManagerdatenEmpfangen', json_encode([
|
||||
'Kopf' => [
|
||||
'Version' => '4.0',
|
||||
'AbsenderID' => $managerId,
|
||||
'EmpfaengerID' => $stationId,
|
||||
'Zeitpunkt' => time(),
|
||||
],
|
||||
'Betriebsart' => $betriebsart,
|
||||
'Sollleistung_W' => $leistung,
|
||||
], JSON_THROW_ON_ERROR));
|
||||
};
|
||||
|
||||
$test->runCase('Alle drei Geraetevarianten erkennen Fahrzeug und Phasen', static function (
|
||||
TestContext $test
|
||||
) use ($definitionen, $stationen): void {
|
||||
foreach ($stationen as $name => $stationId) {
|
||||
IPS_RequestAction($stationId, 'Aktiv', true);
|
||||
$test->assertSame(true, GetValue($test->objectByIdent('FahrzeugVerbunden', $stationId)));
|
||||
$test->assertSame(
|
||||
$definitionen[$name]['Phasenzahl'],
|
||||
GetValue($test->objectByIdent('Phasenzahl', $stationId))
|
||||
);
|
||||
$test->assertSame(false, GetValue($test->objectByIdent('FahrzeugGeladen', $stationId)));
|
||||
IPS_RequestAction($stationId, 'Solarladen', false);
|
||||
$befehl = (string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId));
|
||||
$diagnose = json_encode([
|
||||
'Aktiv' => GetValue($test->objectByIdent('Aktiv', $stationId)),
|
||||
'Ladefreigabe' => GetValue($test->objectByIdent('Ladefreigabe', $stationId)),
|
||||
'Solarladen' => GetValue($test->objectByIdent('Solarladen', $stationId)),
|
||||
'FahrzeugGeladen' => GetValue($test->objectByIdent('FahrzeugGeladen', $stationId)),
|
||||
'Phasenzahl' => GetValue($test->objectByIdent('Phasenzahl', $stationId)),
|
||||
'Status' => IPS_GetInstance($stationId)['InstanceStatus'],
|
||||
'Stoertext' => GetValue($test->objectByIdent('Stoertext', $stationId)),
|
||||
], JSON_THROW_ON_ERROR);
|
||||
$test->assertTrue(str_contains(
|
||||
$befehl,
|
||||
$definitionen[$name]['BefehlUrlTeil']
|
||||
), $name . ': Der erwartete 16-A-Geraetebefehl fehlt. Erhalten: ' . $befehl
|
||||
. '; Diagnose: ' . $diagnose);
|
||||
}
|
||||
});
|
||||
|
||||
$test->runCase('Solar- und Peakbetrieb liefern die Enelix-1-Angebote', static function (
|
||||
TestContext $test
|
||||
) use ($stationen, $anforderungSenden): void {
|
||||
$stationId = $stationen['go-e alt'];
|
||||
IPS_RequestAction($stationId, 'Solarladen', true);
|
||||
$anforderungSenden($stationId, 4150);
|
||||
$befehl = (string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId));
|
||||
$diagnose = json_encode([
|
||||
'Sollleistung' => GetValue($test->objectByIdent('Sollleistung', $stationId)),
|
||||
'SollwertGueltig' => GetValue($test->objectByIdent('SollwertGueltig', $stationId)),
|
||||
'Status' => IPS_GetInstance($stationId)['InstanceStatus'],
|
||||
'Stoertext' => GetValue($test->objectByIdent('Stoertext', $stationId)),
|
||||
], JSON_THROW_ON_ERROR);
|
||||
$test->assertTrue(str_contains(
|
||||
$befehl,
|
||||
'amp=6'
|
||||
), 'Solarladen: Der 6-A-Befehl fehlt. Erhalten: ' . $befehl . '; Diagnose: ' . $diagnose);
|
||||
|
||||
IPS_RequestAction($stationId, 'Solarladen', false);
|
||||
$angebot = (string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId));
|
||||
$test->assertSame('[11000]', $angebot, 'PV ohne Solarladen muss nur das Maximum anbieten.');
|
||||
$abgewiesen = false;
|
||||
try {
|
||||
$anforderungSenden($stationId, 4150);
|
||||
} catch (Throwable $fehler) {
|
||||
$abgewiesen = true;
|
||||
}
|
||||
if (!$abgewiesen) {
|
||||
$abgewiesen = GetValue($test->objectByIdent('SollwertGueltig', $stationId)) !== true
|
||||
|| GetValue($test->objectByIdent('Sollleistung', $stationId)) !== 4150;
|
||||
}
|
||||
$test->assertSame(true, $abgewiesen, 'Normalbetrieb muss eine Zwischenstufe ablehnen.');
|
||||
|
||||
$anforderungSenden($stationId, 4150, 'Peak');
|
||||
$test->assertSame(
|
||||
'[0,4150,4850,5550,6250,6950,7600,8300,9000,9700,10300,11000]',
|
||||
(string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId))
|
||||
);
|
||||
$test->assertTrue(str_contains(
|
||||
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)),
|
||||
'amp=6'
|
||||
), 'Peak ohne Solarladen muss die Ladestufen annehmen.');
|
||||
|
||||
IPS_RequestAction($stationId, 'Solarladen', true);
|
||||
$anforderungSenden($stationId, 0, 'Peak');
|
||||
$test->assertSame(
|
||||
'[0]',
|
||||
(string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId))
|
||||
);
|
||||
$test->assertTrue(str_contains(
|
||||
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)),
|
||||
'alw=0'
|
||||
), 'Peak mit Solarladen muss die Ladestation stoppen.');
|
||||
});
|
||||
};
|
||||
@@ -44,9 +44,33 @@ return static function (TestContext $test): void {
|
||||
]
|
||||
);
|
||||
|
||||
$pufferTemperaturId = $test->createVariable(2, 'Puffertemperatur', 52.0);
|
||||
$aussenTemperaturId = $test->createVariable(2, 'Aussentemperatur', 5.0);
|
||||
$pufferKontakte = [
|
||||
$test->createActionVariable('Pufferspeicher Stufe 1'),
|
||||
$test->createActionVariable('Pufferspeicher Stufe 2'),
|
||||
];
|
||||
$pufferspeicherId = $test->createInstance(
|
||||
'{C92D5EEF-9632-47A5-9659-4B02BF40FBE9}',
|
||||
'Pufferspeicher',
|
||||
[
|
||||
'PufferfuehlerVariableID' => $pufferTemperaturId,
|
||||
'AussentemperaturVariableID' => $aussenTemperaturId,
|
||||
'LeistungsStufen' => json_encode([
|
||||
['Stufe' => 1, 'Leistung' => 1000, 'Schaltkontakt_Stufe' => $pufferKontakte[0]],
|
||||
['Stufe' => 2, 'Leistung' => 2000, 'Schaltkontakt_Stufe' => $pufferKontakte[1]],
|
||||
], JSON_THROW_ON_ERROR),
|
||||
'LastwechselSperrzeit' => 0,
|
||||
'PrioritaetPV' => 2,
|
||||
'PrioritaetPeak' => 2,
|
||||
'DiagnosevariablenAnzeigen' => true,
|
||||
]
|
||||
);
|
||||
|
||||
$zuordnung = [
|
||||
['InstanzID' => $einStufigId, 'Aktiv' => true],
|
||||
['InstanzID' => $warmwasserId, 'Aktiv' => true],
|
||||
['InstanzID' => $pufferspeicherId, 'Aktiv' => true],
|
||||
];
|
||||
$lizenzcode = trim((string) getenv('ENELIX_TEST_LICENSE_CODE'));
|
||||
$managerId = $test->createInstance(
|
||||
@@ -67,8 +91,8 @@ return static function (TestContext $test): void {
|
||||
]
|
||||
);
|
||||
|
||||
$melden = static function () use ($einStufigId, $warmwasserId): void {
|
||||
foreach ([$einStufigId, $warmwasserId] as $instanzId) {
|
||||
$melden = static function () use ($einStufigId, $warmwasserId, $pufferspeicherId): void {
|
||||
foreach ([$einStufigId, $warmwasserId, $pufferspeicherId] as $instanzId) {
|
||||
IPS_RequestAction($instanzId, 'Aktiv', true);
|
||||
IPS_RequestAction($instanzId, 'Melden', true);
|
||||
}
|
||||
@@ -77,10 +101,12 @@ return static function (TestContext $test): void {
|
||||
$netzleistungId,
|
||||
$managerId,
|
||||
$einStufigId,
|
||||
$warmwasserId
|
||||
$warmwasserId,
|
||||
$pufferspeicherId
|
||||
): void {
|
||||
IPS_RequestAction($einStufigId, 'Melden', true);
|
||||
IPS_RequestAction($warmwasserId, 'Melden', true);
|
||||
IPS_RequestAction($pufferspeicherId, 'Melden', true);
|
||||
SetValue($netzleistungId, $netzleistung);
|
||||
IPS_RequestAction($managerId, 'Regeln', true);
|
||||
};
|
||||
@@ -88,6 +114,8 @@ return static function (TestContext $test): void {
|
||||
(bool) GetValue($einKontaktId),
|
||||
(bool) GetValue($warmKontakte[0]),
|
||||
(bool) GetValue($warmKontakte[1]),
|
||||
(bool) GetValue($pufferKontakte[0]),
|
||||
(bool) GetValue($pufferKontakte[1]),
|
||||
];
|
||||
$warteAufKontakte = static function (array $erwartet, string $schritt) use (
|
||||
$test,
|
||||
@@ -150,20 +178,20 @@ return static function (TestContext $test): void {
|
||||
|
||||
$test->runCase('Manager und alle vorhandenen Verbrauchertypen sind verknüpft', static function (
|
||||
TestContext $test
|
||||
) use ($managerId, $einStufigId, $warmwasserId, $melden): void {
|
||||
) use ($managerId, $einStufigId, $warmwasserId, $pufferspeicherId, $melden): void {
|
||||
IPS_RequestAction($managerId, 'Aktiv', true);
|
||||
$melden();
|
||||
IPS_RequestAction($managerId, 'Regeln', true);
|
||||
|
||||
foreach ([$managerId, $einStufigId, $warmwasserId] as $instanzId) {
|
||||
foreach ([$managerId, $einStufigId, $warmwasserId, $pufferspeicherId] as $instanzId) {
|
||||
$test->assertInstanceStatus($instanzId);
|
||||
}
|
||||
$test->assertSame(
|
||||
2,
|
||||
3,
|
||||
GetValue($test->objectByIdent('VerbraucherAnzahl', $managerId))
|
||||
);
|
||||
$test->assertSame(
|
||||
2,
|
||||
3,
|
||||
GetValue($test->objectByIdent('VerbraucherVerfuegbar', $managerId))
|
||||
);
|
||||
});
|
||||
@@ -172,22 +200,22 @@ return static function (TestContext $test): void {
|
||||
TestContext $test
|
||||
) use ($managerId, $regeln, $warteAufKontakte): void {
|
||||
$regeln(-3000.0);
|
||||
$warteAufKontakte([true, false, true], 'Netz -3000 W');
|
||||
$warteAufKontakte([true, false, true, false, false], 'Netz -3000 W');
|
||||
$test->assertSame('PV', GetValue($test->objectByIdent('Betriebsart', $managerId)));
|
||||
|
||||
$regeln(-1000.0);
|
||||
$warteAufKontakte([true, false, true], 'Netz -1000 W');
|
||||
$warteAufKontakte([true, false, true, false, false], 'Netz -1000 W');
|
||||
$regeln(0.0);
|
||||
$warteAufKontakte([true, false, true], 'Netz 0 W');
|
||||
$warteAufKontakte([true, false, true, false, false], 'Netz 0 W');
|
||||
|
||||
IPS_Sleep(1100);
|
||||
$regeln(1000.0);
|
||||
$warteAufKontakte([true, true, false], 'Netz +1000 W');
|
||||
$warteAufKontakte([false, false, false, false, false], 'Netz +1000 W');
|
||||
$test->assertSame('Peak', GetValue($test->objectByIdent('Betriebsart', $managerId)));
|
||||
|
||||
IPS_Sleep(1100);
|
||||
$regeln(3000.0);
|
||||
$warteAufKontakte([false, false, false], 'Netz +3000 W');
|
||||
$warteAufKontakte([false, false, false, false, false], 'Netz +3000 W');
|
||||
});
|
||||
|
||||
$test->runCase('Keep-alive ist aktiv und erneuert unveränderte Sollwerte', static function (
|
||||
@@ -216,7 +244,7 @@ return static function (TestContext $test): void {
|
||||
$melden();
|
||||
IPS_RequestAction($managerId, 'Regeln', false);
|
||||
$daten = $verbraucherstatus();
|
||||
$test->assertSame(2, count($daten['Verbraucher'] ?? []));
|
||||
$test->assertSame(3, count($daten['Verbraucher'] ?? []));
|
||||
|
||||
SetValue($temperaturId, 53.0);
|
||||
$test->waitUntil(static function () use (
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Belevo\EnelixEMS\SymconTest\TestContext;
|
||||
|
||||
return static function (TestContext $test): void {
|
||||
$pufferId = $test->createVariable(2, 'Puffertemperatur', 40.0, null, '~Temperature');
|
||||
$aussenId = $test->createVariable(2, 'Aussentemperatur', 5.0, null, '~Temperature');
|
||||
$wpSollId = $test->createVariable(2, 'WP Solltemperatur', 50.0, null, '~Temperature');
|
||||
$kontakte = [
|
||||
$test->createActionVariable('Puffer Stufe 1'),
|
||||
$test->createActionVariable('Puffer Stufe 2'),
|
||||
];
|
||||
$stufen = [
|
||||
['Stufe' => 1, 'Leistung' => 1000, 'Schaltkontakt_Stufe' => $kontakte[0]],
|
||||
['Stufe' => 2, 'Leistung' => 2000, 'Schaltkontakt_Stufe' => $kontakte[1]],
|
||||
];
|
||||
$verbraucherId = $test->createInstance(
|
||||
'{C92D5EEF-9632-47A5-9659-4B02BF40FBE9}',
|
||||
'Pufferspeicher',
|
||||
[
|
||||
'PufferfuehlerVariableID' => $pufferId,
|
||||
'AussentemperaturVariableID' => $aussenId,
|
||||
'WaermepumpenSolltemperaturVariableID' => $wpSollId,
|
||||
'LeistungsStufen' => json_encode($stufen, JSON_THROW_ON_ERROR),
|
||||
'FusspunktVorlauftemperatur' => 35.0,
|
||||
'HeizkurvenSteigung' => 1.0,
|
||||
'HeizkurveMinimaltemperatur' => 20.0,
|
||||
'HeizkurveMaximaltemperatur' => 80.0,
|
||||
'Hysterese' => 5.0,
|
||||
'LastwechselSperrzeit' => 0,
|
||||
'TemperaturMaxAlter' => 120,
|
||||
'DiagnosevariablenAnzeigen' => true,
|
||||
]
|
||||
);
|
||||
$managerId = $test->createInstance(
|
||||
'{6F771B18-59D4-4C8A-B951-3B2FE9F6A2C4}',
|
||||
'Hilfsmanager Pufferspeicher',
|
||||
[
|
||||
'AutomatischeSuche' => false,
|
||||
'VerbraucherZuordnung' => json_encode([
|
||||
['InstanzID' => $verbraucherId, 'Aktiv' => true],
|
||||
], JSON_THROW_ON_ERROR),
|
||||
]
|
||||
);
|
||||
|
||||
$managerdatenSenden = static function (
|
||||
string $betriebsart,
|
||||
?int $leistung
|
||||
) use ($managerId, $verbraucherId): void {
|
||||
IPS_RequestAction($verbraucherId, 'ManagerdatenEmpfangen', json_encode([
|
||||
'Kopf' => [
|
||||
'Version' => '4.0',
|
||||
'AbsenderID' => $managerId,
|
||||
'EmpfaengerID' => $verbraucherId,
|
||||
'Zeitpunkt' => time(),
|
||||
],
|
||||
'Betriebsart' => $betriebsart,
|
||||
'Sollleistung_W' => $leistung,
|
||||
], JSON_THROW_ON_ERROR));
|
||||
};
|
||||
$kontaktzustand = static fn (): array => array_map(
|
||||
static fn (int $id): bool => (bool) GetValue($id),
|
||||
$kontakte
|
||||
);
|
||||
|
||||
$test->runCase('Instanz und Variablen werden angelegt', static function (
|
||||
TestContext $test
|
||||
) use ($verbraucherId): void {
|
||||
$test->assertInstanceStatus($verbraucherId);
|
||||
foreach ([
|
||||
'Aktiv',
|
||||
'Puffertemperatur',
|
||||
'Aussentemperatur',
|
||||
'Solltemperatur',
|
||||
'Heizbedarf',
|
||||
'Istleistung',
|
||||
'Sollleistung',
|
||||
'AktiveStufe',
|
||||
'TemperaturenGueltig',
|
||||
] as $ident) {
|
||||
$test->objectByIdent($ident, $verbraucherId);
|
||||
}
|
||||
});
|
||||
|
||||
$test->runCase('Unter der Einschaltschwelle kann PV eine Stufe schalten', static function (
|
||||
TestContext $test
|
||||
) use ($verbraucherId, $managerdatenSenden, $kontaktzustand): void {
|
||||
IPS_RequestAction($verbraucherId, 'Aktiv', true);
|
||||
$managerdatenSenden('PV', null);
|
||||
$test->assertSame(true, GetValue($test->objectByIdent('Heizbedarf', $verbraucherId)));
|
||||
|
||||
$managerdatenSenden('PV', 2000);
|
||||
$test->waitUntil(static fn (): bool => $kontaktzustand() === [false, true]);
|
||||
$test->assertSame([false, true], $kontaktzustand());
|
||||
});
|
||||
|
||||
$test->runCase('In der Hysterese und oberhalb des Sollwerts wird ausgeschaltet', static function (
|
||||
TestContext $test
|
||||
) use ($pufferId, $verbraucherId, $kontaktzustand): void {
|
||||
SetValue($pufferId, 47.0);
|
||||
IPS_RequestAction($verbraucherId, 'Melden', true);
|
||||
$test->waitUntil(static fn (): bool => $kontaktzustand() === [false, false]);
|
||||
$test->assertSame(false, GetValue($test->objectByIdent('Heizbedarf', $verbraucherId)));
|
||||
|
||||
SetValue($pufferId, 55.0);
|
||||
IPS_RequestAction($verbraucherId, 'Melden', true);
|
||||
$test->assertSame([false, false], $kontaktzustand());
|
||||
});
|
||||
|
||||
$test->runCase('Peakbetrieb sperrt den Pufferspeicher unabhaengig von der Temperatur', static function (
|
||||
TestContext $test
|
||||
) use ($pufferId, $verbraucherId, $managerdatenSenden, $kontaktzustand): void {
|
||||
SetValue($pufferId, 20.0);
|
||||
$managerdatenSenden('Peak', null);
|
||||
$test->assertSame(false, GetValue($test->objectByIdent('Heizbedarf', $verbraucherId)));
|
||||
$test->waitUntil(static fn (): bool => $kontaktzustand() === [false, false]);
|
||||
|
||||
$abgewiesen = false;
|
||||
try {
|
||||
$managerdatenSenden('Peak', 1000);
|
||||
} catch (Throwable $fehler) {
|
||||
$abgewiesen = true;
|
||||
}
|
||||
if (!$abgewiesen) {
|
||||
$abgewiesen = GetValue($test->objectByIdent('SollwertGueltig', $verbraucherId)) !== true
|
||||
|| GetValue($test->objectByIdent('Sollleistung', $verbraucherId)) !== 1000;
|
||||
}
|
||||
$test->assertSame(true, $abgewiesen, 'Peak darf keine Heizstufe anbieten.');
|
||||
$test->assertSame([false, false], $kontaktzustand());
|
||||
});
|
||||
|
||||
$test->runCase('Lokales Ausschalten schaltet jede Stufe aus', static function (
|
||||
TestContext $test
|
||||
) use ($verbraucherId, $kontaktzustand): void {
|
||||
IPS_RequestAction($verbraucherId, 'Aktiv', false);
|
||||
$test->waitUntil(static fn (): bool => $kontaktzustand() === [false, false]);
|
||||
$test->assertSame([false, false], $kontaktzustand());
|
||||
});
|
||||
|
||||
$test->runCase('WP-Button kalibriert den Heizkurven-Fusspunkt', static function (
|
||||
TestContext $test
|
||||
) use ($verbraucherId): void {
|
||||
IPS_SetProperty($verbraucherId, 'FusspunktVorlauftemperatur', 30.0);
|
||||
IPS_ApplyChanges($verbraucherId);
|
||||
IPS_RequestAction($verbraucherId, 'HeizkurveVonWaermepumpeUebernehmen', 0);
|
||||
|
||||
$test->assertEquals(
|
||||
35.0,
|
||||
(float) IPS_GetProperty($verbraucherId, 'FusspunktVorlauftemperatur'),
|
||||
0.001
|
||||
);
|
||||
});
|
||||
};
|
||||
@@ -32,17 +32,21 @@ return static function (TestContext $test): void {
|
||||
]
|
||||
);
|
||||
|
||||
$anforderungSenden = static function (int $leistung) use (
|
||||
$anforderungSenden = static function (
|
||||
?int $leistung,
|
||||
string $betriebsart = 'PV'
|
||||
) use (
|
||||
$managerId,
|
||||
$verbraucherId
|
||||
): void {
|
||||
$paket = [
|
||||
'Kopf' => [
|
||||
'Version' => '3.0',
|
||||
'Version' => '4.0',
|
||||
'AbsenderID' => $managerId,
|
||||
'EmpfaengerID' => $verbraucherId,
|
||||
'Zeitpunkt' => time(),
|
||||
],
|
||||
'Betriebsart' => $betriebsart,
|
||||
'Sollleistung_W' => $leistung,
|
||||
];
|
||||
IPS_RequestAction(
|
||||
@@ -64,6 +68,28 @@ return static function (TestContext $test): void {
|
||||
}
|
||||
});
|
||||
|
||||
$test->runCase('PV und Peak liefern unterschiedliche Leistungsangebote', static function (
|
||||
TestContext $test
|
||||
) use ($verbraucherId, $anforderungSenden): void {
|
||||
IPS_RequestAction($verbraucherId, 'Aktiv', true);
|
||||
IPS_Sleep(2100);
|
||||
$anforderungSenden(null, 'Peak');
|
||||
|
||||
$abgewiesen = false;
|
||||
try {
|
||||
$anforderungSenden(1200, 'Peak');
|
||||
} catch (Throwable $fehler) {
|
||||
$abgewiesen = true;
|
||||
}
|
||||
if (!$abgewiesen) {
|
||||
$abgewiesen = GetValue($test->objectByIdent('SollwertGueltig', $verbraucherId)) !== true
|
||||
|| GetValue($test->objectByIdent('Sollleistung', $verbraucherId)) !== 1200;
|
||||
}
|
||||
$test->assertSame(true, $abgewiesen, 'Peak darf die Nennleistung nicht anbieten.');
|
||||
|
||||
$anforderungSenden(null, 'PV');
|
||||
});
|
||||
|
||||
$test->runCase('Nur angebotene Leistungsanforderungen werden angenommen', static function (
|
||||
TestContext $test
|
||||
) use (
|
||||
@@ -143,7 +169,7 @@ return static function (TestContext $test): void {
|
||||
SetValue($rueckmeldungId, true);
|
||||
});
|
||||
|
||||
$test->runCase('Tägliche Mindestlaufzeit wird spätestens rechtzeitig erzwungen', static function (
|
||||
$test->runCase('Peak kann die Tagesmindestlaufzeit ohne angebotene Sperre erzwingen', static function (
|
||||
TestContext $test
|
||||
) use (
|
||||
$verbraucherId,
|
||||
@@ -155,7 +181,13 @@ return static function (TestContext $test): void {
|
||||
$anforderungSenden(0);
|
||||
$test->waitUntil(static fn (): bool => GetValue($kontaktId) === false);
|
||||
SetValue($rueckmeldungId, false);
|
||||
$test->waitUntil(static fn (): bool => GetValue(
|
||||
$test->objectByIdent('Schaltzustand', $verbraucherId)
|
||||
) === false);
|
||||
IPS_Sleep(2100);
|
||||
|
||||
$anforderungSenden(null, 'Peak');
|
||||
IPS_SetProperty($verbraucherId, 'PeakSperreBeiMindestlaufzeitAnbieten', false);
|
||||
IPS_SetProperty($verbraucherId, 'Mindestlaufzeit', 86400);
|
||||
IPS_ApplyChanges($verbraucherId);
|
||||
$test->waitUntil(static fn (): bool => GetValue($kontaktId) === true);
|
||||
@@ -163,9 +195,14 @@ return static function (TestContext $test): void {
|
||||
$test->objectByIdent('Sollleistung', $verbraucherId)
|
||||
));
|
||||
SetValue($rueckmeldungId, true);
|
||||
$test->waitUntil(static fn (): bool => GetValue(
|
||||
$test->objectByIdent('Schaltzustand', $verbraucherId)
|
||||
) === true);
|
||||
|
||||
IPS_SetProperty($verbraucherId, 'Mindestlaufzeit', 0);
|
||||
IPS_SetProperty($verbraucherId, 'PeakSperreBeiMindestlaufzeitAnbieten', true);
|
||||
IPS_ApplyChanges($verbraucherId);
|
||||
$anforderungSenden(null, 'PV');
|
||||
});
|
||||
|
||||
$test->runCase('Physische Rückmeldung bestätigt und überwacht den Zustand', static function (
|
||||
|
||||
@@ -38,11 +38,13 @@ return static function (TestContext $test): void {
|
||||
'DiagnosevariablenAnzeigen' => true,
|
||||
]
|
||||
);
|
||||
$lizenzcode = trim((string) getenv('ENELIX_TEST_LICENSE_CODE'));
|
||||
$managerId = $test->createInstance(
|
||||
'{6F771B18-59D4-4C8A-B951-3B2FE9F6A2C4}',
|
||||
'Hilfsmanager',
|
||||
[
|
||||
'NetzleistungVariableID' => $netzleistungId,
|
||||
'Lizenzcode' => $lizenzcode,
|
||||
'AutomatischeSuche' => false,
|
||||
'VerbraucherZuordnung' => json_encode([
|
||||
['InstanzID' => $verbraucherId, 'Aktiv' => true],
|
||||
@@ -88,6 +90,17 @@ return static function (TestContext $test): void {
|
||||
IPS_RequestAction($managerId, 'Regeln', true);
|
||||
};
|
||||
|
||||
if ($lizenzcode === '') {
|
||||
$test->runCase('Manager bleibt ohne Lizenz sicher gesperrt', static function (
|
||||
TestContext $test
|
||||
) use ($verbraucherId, $managerId): void {
|
||||
$test->assertInstanceStatus($verbraucherId);
|
||||
$test->assertInstanceStatus($managerId, 203);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$test->runCase('Instanzen und Diagnosevariablen werden angelegt', static function (
|
||||
TestContext $test
|
||||
) use ($verbraucherId, $managerId): void {
|
||||
@@ -119,7 +132,7 @@ return static function (TestContext $test): void {
|
||||
);
|
||||
});
|
||||
|
||||
$test->runCase('Unter Minimum wird in PV und Peak bis über die Hysterese geheizt', static function (
|
||||
$test->runCase('Unter Minimum erzwingt PV das Maximum und Peak bietet alle Stufen', static function (
|
||||
TestContext $test
|
||||
) use (
|
||||
$temperaturSetzen,
|
||||
@@ -132,17 +145,19 @@ return static function (TestContext $test): void {
|
||||
$warteAufKontakte([false, false, true]);
|
||||
$test->assertSame('PV', GetValue($test->objectByIdent('Betriebsart', $managerId)));
|
||||
|
||||
$managerRegeln(3000.0);
|
||||
$warteAufKontakte([false, false, true]);
|
||||
IPS_Sleep(1100);
|
||||
$managerRegeln(1000.0);
|
||||
$warteAufKontakte([false, true, false]);
|
||||
$test->assertSame('Peak', GetValue($test->objectByIdent('Betriebsart', $managerId)));
|
||||
|
||||
$temperaturSetzen(49.9);
|
||||
$managerRegeln(3000.0);
|
||||
$warteAufKontakte([false, false, true]);
|
||||
IPS_Sleep(1100);
|
||||
$temperaturSetzen(47.0);
|
||||
$managerRegeln(1000.0);
|
||||
$warteAufKontakte([true, false, false]);
|
||||
|
||||
IPS_Sleep(1100);
|
||||
$temperaturSetzen(50.0);
|
||||
$managerRegeln(3000.0);
|
||||
$managerRegeln(1000.0);
|
||||
$warteAufKontakte([false, false, false]);
|
||||
});
|
||||
|
||||
@@ -170,12 +185,12 @@ return static function (TestContext $test): void {
|
||||
$managerRegeln(-3000.0);
|
||||
$warteAufKontakte([false, false, false]);
|
||||
|
||||
$temperaturSetzen(55.0);
|
||||
$temperaturSetzen(54.9);
|
||||
$managerRegeln(-3000.0);
|
||||
$warteAufKontakte([false, false, true]);
|
||||
});
|
||||
|
||||
$test->runCase('Legionellenziel erlaubt Peak-Stufen und lädt in PV maximal', static function (
|
||||
$test->runCase('Erhöhtes Maximalziel bleibt im freien Peakbetrieb gesperrt', static function (
|
||||
TestContext $test
|
||||
) use (
|
||||
$verbraucherId,
|
||||
@@ -190,10 +205,10 @@ return static function (TestContext $test): void {
|
||||
|
||||
IPS_Sleep(1100);
|
||||
$managerRegeln(2000.0);
|
||||
$warteAufKontakte([true, false, false]);
|
||||
$warteAufKontakte([false, false, false]);
|
||||
});
|
||||
|
||||
$test->runCase('Zeitplan erzwingt rechtzeitiges Aufheizen wie ein Minimum', static function (
|
||||
$test->runCase('Zeitplan bietet in Peak alle Stufen und erzwingt in PV das Maximum', static function (
|
||||
TestContext $test
|
||||
) use (
|
||||
$verbraucherId,
|
||||
@@ -211,6 +226,12 @@ return static function (TestContext $test): void {
|
||||
['Uhrzeit' => date('H:i', time() + 60), 'Solltemperatur' => 60],
|
||||
], JSON_THROW_ON_ERROR));
|
||||
IPS_ApplyChanges($verbraucherId);
|
||||
$test->assertSame(true, GetValue(
|
||||
$test->objectByIdent('AenderungMoeglich', $verbraucherId)
|
||||
));
|
||||
$warteAufKontakte([false, false, false]);
|
||||
|
||||
$managerRegeln(-3000.0);
|
||||
$warteAufKontakte([false, false, true]);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ final class SymconTestContractTest extends TestCase
|
||||
public function testAffectedModuleResolverSelectsAllMatches(): void
|
||||
{
|
||||
self::assertSame(
|
||||
['Manager', 'VerbraucherEinStufig', 'Warmwassererwaermer'],
|
||||
['LadestationStandAlone', 'Manager', 'Pufferspeicher', 'VerbraucherEinStufig', 'Warmwassererwaermer'],
|
||||
$this->resolveAffectedModules(['libs/Nachrichtenvertrag.php'])
|
||||
);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ final class SymconTestContractTest extends TestCase
|
||||
public function testAffectedModuleResolverSelectsAllModulesForFrameworkChanges(): void
|
||||
{
|
||||
self::assertSame(
|
||||
['Manager', 'VerbraucherEinStufig', 'Warmwassererwaermer'],
|
||||
['LadestationStandAlone', 'Manager', 'Pufferspeicher', 'VerbraucherEinStufig', 'Warmwassererwaermer'],
|
||||
$this->resolveAffectedModules(['tests/Symcon/TestContext.php'])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,23 +16,43 @@ final class EinStufigReglerTest extends TestCase
|
||||
{
|
||||
self::assertSame(
|
||||
[0, 3500],
|
||||
EinStufigRegler::leistungsangebot(3500, 0, true, true, false)
|
||||
EinStufigRegler::leistungsangebot(3500, 0, true, true, false, false)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGesperrtesOderErzwungenesAngebotEnthaeltNurIstleistung(): void
|
||||
public function testPeakbetriebBietetBeiFreierSchaltungNurAus(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[0],
|
||||
EinStufigRegler::leistungsangebot(3500, 0, true, true, false, true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testTechnischGesperrtesAngebotEnthaeltNurIstleistung(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[3500],
|
||||
EinStufigRegler::leistungsangebot(3500, 3500, true, false, false)
|
||||
);
|
||||
self::assertSame(
|
||||
[0],
|
||||
EinStufigRegler::leistungsangebot(3500, 0, true, true, true)
|
||||
EinStufigRegler::leistungsangebot(3500, 3500, true, false, false, true)
|
||||
);
|
||||
self::assertSame(
|
||||
[3500],
|
||||
EinStufigRegler::leistungsangebot(3500, 3500, false, true, false)
|
||||
EinStufigRegler::leistungsangebot(3500, 3500, false, true, false, true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testPeakSperreBeiMindestlaufzeitIstKonfigurierbar(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[0, 3500],
|
||||
EinStufigRegler::leistungsangebot(3500, 0, true, true, true, true, true)
|
||||
);
|
||||
self::assertSame(
|
||||
[3500],
|
||||
EinStufigRegler::leistungsangebot(3500, 0, true, true, true, true, false)
|
||||
);
|
||||
self::assertSame(
|
||||
[3500],
|
||||
EinStufigRegler::leistungsangebot(3500, 0, true, true, true, false, true)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +60,7 @@ final class EinStufigReglerTest extends TestCase
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
EinStufigRegler::leistungsangebot(3500, 1200, true, true, false);
|
||||
EinStufigRegler::leistungsangebot(3500, 1200, true, true, false, false);
|
||||
}
|
||||
|
||||
public function testFreigabeVerwendetZustandsabhaengigeMindestdauer(): void
|
||||
|
||||
@@ -65,6 +65,7 @@ final class VerbraucherEinStufigModulstrukturTest extends TestCase
|
||||
'SchaltkontaktInvertiert',
|
||||
'RueckmeldungVariableID',
|
||||
'Mindestlaufzeit',
|
||||
'PeakSperreBeiMindestlaufzeitAnbieten',
|
||||
'Mindesteinschaltdauer',
|
||||
'Mindestausschaltdauer',
|
||||
'DiagnosevariablenAnzeigen',
|
||||
@@ -130,7 +131,7 @@ final class VerbraucherEinStufigModulstrukturTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testModulVerwendetAusschliesslichDenVertrag30(): void
|
||||
public function testModulVerwendetVertrag40UndBetriebsartabhaengigesAngebot(): void
|
||||
{
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
|
||||
@@ -138,6 +139,9 @@ final class VerbraucherEinStufigModulstrukturTest extends TestCase
|
||||
self::assertStringContainsString('ManagerdatenEmpfangen(array $daten)', $modul);
|
||||
self::assertStringContainsString('Nachrichtenvertrag::pruefeManagerdaten', $modul);
|
||||
self::assertStringContainsString('Nachrichtenvertrag::pruefeVerbraucherdaten', $modul);
|
||||
self::assertStringContainsString("['Betriebsart']", $modul);
|
||||
self::assertStringContainsString('BETRIEBSART_PEAK', $modul);
|
||||
self::assertStringContainsString("'Betriebsart' =>", $modul);
|
||||
self::assertStringNotContainsString("RegisterVariableString('PowerSteps'", $modul);
|
||||
self::assertStringNotContainsString("RegisterPropertyInteger('ManagerID'", $modul);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,46 @@ final class WarmwasserReglerTest extends TestCase
|
||||
self::assertSame(0, WarmwasserRegler::stufeFuerLeistung($stufen, 0));
|
||||
}
|
||||
|
||||
public function testPeakBietetUnterMinimumUndBeiAktiverUntererHystereseAlleStufen(): void
|
||||
{
|
||||
$werte = [0, 1000, 2000];
|
||||
|
||||
self::assertSame(
|
||||
$werte,
|
||||
WarmwasserRegler::leistungsangebot(true, 44.0, 50.0, 60.0, 5.0, false, $werte)
|
||||
);
|
||||
self::assertSame(
|
||||
$werte,
|
||||
WarmwasserRegler::leistungsangebot(true, 52.0, 50.0, 60.0, 5.0, true, $werte)
|
||||
);
|
||||
self::assertSame(
|
||||
[0],
|
||||
WarmwasserRegler::leistungsangebot(true, 52.0, 50.0, 60.0, 5.0, false, $werte)
|
||||
);
|
||||
}
|
||||
|
||||
public function testPvErzwingtUnterMinimumMaximumUndBietetSonstZustandsabhaengigAn(): void
|
||||
{
|
||||
$werte = [0, 1000, 2000];
|
||||
|
||||
self::assertSame(
|
||||
[2000],
|
||||
WarmwasserRegler::leistungsangebot(false, 44.0, 50.0, 60.0, 5.0, false, $werte)
|
||||
);
|
||||
self::assertSame(
|
||||
$werte,
|
||||
WarmwasserRegler::leistungsangebot(false, 52.0, 50.0, 60.0, 5.0, false, $werte)
|
||||
);
|
||||
self::assertSame(
|
||||
$werte,
|
||||
WarmwasserRegler::leistungsangebot(false, 58.0, 50.0, 60.0, 5.0, true, $werte)
|
||||
);
|
||||
self::assertSame(
|
||||
[0],
|
||||
WarmwasserRegler::leistungsangebot(false, 58.0, 50.0, 60.0, 5.0, false, $werte)
|
||||
);
|
||||
}
|
||||
|
||||
public function testDoppelteKontakteWerdenAbgewiesen(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
Reference in New Issue
Block a user