This commit is contained in:
@@ -100,6 +100,7 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
||||
$this->RegisterAttributeInteger('PhasenerkennungSeit', 0);
|
||||
$this->RegisterAttributeInteger('PhasenerkennungVersion', 0);
|
||||
$this->RegisterAttributeBoolean('LadeleistungSeitFreigabeErkannt', false);
|
||||
$this->RegisterAttributeInteger('GeraeteMaximalstrom', 32);
|
||||
$this->RegisterAttributeInteger('ErkannterMaximalstrom', 32);
|
||||
$this->RegisterAttributeInteger('FahrzeugstromKandidat', 0);
|
||||
$this->RegisterAttributeInteger('FahrzeugstromKandidatSeit', 0);
|
||||
@@ -236,7 +237,6 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
||||
if ((bool) $wert) {
|
||||
$this->SetTimerInterval('RueckmeldungVerzoegert', 0);
|
||||
}
|
||||
$this->aktualisiere(false);
|
||||
$this->sendeVerbraucherdaten();
|
||||
return;
|
||||
|
||||
@@ -315,6 +315,7 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
||||
$phasenzahl = $this->ReadAttributeInteger('ZustandPhasenzahl');
|
||||
$maximalstrom = min(
|
||||
$this->ReadPropertyInteger('MaximalerLadestrom'),
|
||||
max(6, $this->ReadAttributeInteger('GeraeteMaximalstrom')),
|
||||
max(6, $this->ReadAttributeInteger('ErkannterMaximalstrom'))
|
||||
);
|
||||
$this->setzeSichtbareVariable('FahrzeugMaximalstrom', $maximalstrom);
|
||||
@@ -423,6 +424,15 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
||||
$this->ReadPropertyInteger('Geraetetyp'),
|
||||
$antwort
|
||||
);
|
||||
if (isset($rohstatus['Sollstrom_A'])) {
|
||||
$geraeteSollstrom = (int) $rohstatus['Sollstrom_A'];
|
||||
if ($geraeteSollstrom === 0 || ($geraeteSollstrom >= 6 && $geraeteSollstrom <= 32)) {
|
||||
$this->WriteAttributeInteger('LetzterGesetzterStrom', $geraeteSollstrom);
|
||||
}
|
||||
}
|
||||
if (isset($rohstatus['Maximalstrom_A'])) {
|
||||
$this->WriteAttributeInteger('GeraeteMaximalstrom', (int) $rohstatus['Maximalstrom_A']);
|
||||
}
|
||||
|
||||
$warVerbunden = $this->ReadAttributeBoolean('ZustandFahrzeugVerbunden');
|
||||
$verbunden = $rohstatus['Rohstatus'] !== 1;
|
||||
|
||||
+15
-3
@@ -219,6 +219,11 @@ class Manager extends IPSModule implements ManagerSchnittstelle
|
||||
0,
|
||||
"IPS_RequestAction(\$_IPS['TARGET'], 'Regeln', true);"
|
||||
);
|
||||
$this->RegisterTimer(
|
||||
'RegelungVerzoegert',
|
||||
0,
|
||||
"IPS_RequestAction(\$_IPS['TARGET'], 'RegelnVerzoegert', false);"
|
||||
);
|
||||
$this->RegisterTimer(
|
||||
'PrognoseSenden',
|
||||
0,
|
||||
@@ -252,6 +257,7 @@ class Manager extends IPSModule implements ManagerSchnittstelle
|
||||
$this->SetTimerInterval('Regelzyklus', 0);
|
||||
$this->SetTimerInterval('VorgabenErneuern', 0);
|
||||
$this->SetTimerInterval('KeepAlive', 0);
|
||||
$this->SetTimerInterval('RegelungVerzoegert', 0);
|
||||
$this->SetTimerInterval('PrognoseSenden', 0);
|
||||
$this->SetTimerInterval('StoerungenSenden', 0);
|
||||
$this->SetTimerInterval('MesswerteAufzeichnen', 0);
|
||||
@@ -263,6 +269,7 @@ class Manager extends IPSModule implements ManagerSchnittstelle
|
||||
$this->SetTimerInterval('Regelzyklus', 0);
|
||||
$this->SetTimerInterval('VorgabenErneuern', 0);
|
||||
$this->SetTimerInterval('KeepAlive', $this->ReadPropertyInteger('KeepAlive') * 1000);
|
||||
$this->SetTimerInterval('RegelungVerzoegert', 0);
|
||||
$this->SetTimerInterval('PrognoseSenden', 0);
|
||||
$this->SetTimerInterval(
|
||||
'StoerungenSenden',
|
||||
@@ -456,6 +463,11 @@ class Manager extends IPSModule implements ManagerSchnittstelle
|
||||
$this->regeln((bool) $wert);
|
||||
return;
|
||||
|
||||
case 'RegelnVerzoegert':
|
||||
$this->SetTimerInterval('RegelungVerzoegert', 0);
|
||||
$this->regeln(false);
|
||||
return;
|
||||
|
||||
case 'PrognoseSenden':
|
||||
$this->sendePrognoseTelemetrie();
|
||||
return;
|
||||
@@ -624,9 +636,9 @@ class Manager extends IPSModule implements ManagerSchnittstelle
|
||||
$this->WriteAttributeString('VerbraucherCache', json_encode($cache, JSON_THROW_ON_ERROR));
|
||||
$this->aktualisiereEnergieflusswerte();
|
||||
$this->aktualisiereDiagrammMesswerte();
|
||||
if ($this->GetBuffer('VerbraucherSynchronisierungAktiv') !== '1') {
|
||||
$this->regeln(false);
|
||||
}
|
||||
|
||||
// Den synchronen Rueckruf in die noch meldende Verbraucherinstanz vermeiden.
|
||||
$this->SetTimerInterval('RegelungVerzoegert', 100);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $daten */
|
||||
|
||||
@@ -91,7 +91,7 @@ final class LadestationAdapter
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{Rohstatus: int, Istleistung_W: float, Iststrom_A?: float, Phasenzahl?: int}
|
||||
* @return array{Rohstatus: int, Istleistung_W: float, Sollstrom_A?: int, Maximalstrom_A?: int, Iststrom_A?: float, Phasenzahl?: int}
|
||||
*/
|
||||
public static function dekodiereStatus(int $geraetetyp, string $antwort): array
|
||||
{
|
||||
@@ -115,6 +115,20 @@ final class LadestationAdapter
|
||||
'Rohstatus' => (int) $daten['car'],
|
||||
'Istleistung_W' => (float) $daten['nrg'][11] * $leistungsfaktor,
|
||||
];
|
||||
if (isset($daten['amp']) && is_numeric($daten['amp'])) {
|
||||
$sollstrom = (int) $daten['amp'];
|
||||
$freigabeEntzogen = isset($daten['alw']) && $daten['alw'] === false;
|
||||
$erzwungenAus = $geraetetyp === self::GO_E_GEMINI
|
||||
&& isset($daten['frc'])
|
||||
&& (int) $daten['frc'] === 1;
|
||||
$status['Sollstrom_A'] = $freigabeEntzogen || $erzwungenAus ? 0 : $sollstrom;
|
||||
}
|
||||
if (isset($daten['ama']) && is_numeric($daten['ama'])) {
|
||||
$maximalstrom = (int) $daten['ama'];
|
||||
if ($maximalstrom >= 6 && $maximalstrom <= 32) {
|
||||
$status['Maximalstrom_A'] = $maximalstrom;
|
||||
}
|
||||
}
|
||||
if (isset($daten['nrg'][4], $daten['nrg'][5], $daten['nrg'][6])
|
||||
&& is_numeric($daten['nrg'][4])
|
||||
&& is_numeric($daten['nrg'][5])
|
||||
|
||||
@@ -13,7 +13,7 @@ final class LadestationAdapterTest extends TestCase
|
||||
/**
|
||||
* @dataProvider statusFaelle
|
||||
* @param array<string, string> $konfiguration
|
||||
* @param array{Rohstatus: int, Istleistung_W: float, Iststrom_A?: float, Phasenzahl?: int} $erwartet
|
||||
* @param array{Rohstatus: int, Istleistung_W: float, Sollstrom_A?: int, Maximalstrom_A?: int, Iststrom_A?: float, Phasenzahl?: int} $erwartet
|
||||
*/
|
||||
public function testStatusaufrufUndDekodierungFuerAlleGeraete(
|
||||
int $geraetetyp,
|
||||
@@ -52,6 +52,8 @@ final class LadestationAdapterTest extends TestCase
|
||||
[
|
||||
'Rohstatus' => 2,
|
||||
'Istleistung_W' => 11000.0,
|
||||
'Sollstrom_A' => 16,
|
||||
'Maximalstrom_A' => 16,
|
||||
'Iststrom_A' => 16.0,
|
||||
'Phasenzahl' => 3,
|
||||
],
|
||||
@@ -64,6 +66,8 @@ final class LadestationAdapterTest extends TestCase
|
||||
[
|
||||
'Rohstatus' => 2,
|
||||
'Istleistung_W' => 2300.0,
|
||||
'Sollstrom_A' => 16,
|
||||
'Maximalstrom_A' => 16,
|
||||
'Iststrom_A' => 9.8,
|
||||
'Phasenzahl' => 1,
|
||||
],
|
||||
@@ -81,6 +85,20 @@ final class LadestationAdapterTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
public function testGoEAusFreigabeWirdAlsNullSollstromDekodiert(): void
|
||||
{
|
||||
$daten = json_decode($this->goEAntwort(2, 0, [0, 0, 0]), true, 512, JSON_THROW_ON_ERROR);
|
||||
$daten['alw'] = false;
|
||||
$daten['frc'] = 1;
|
||||
|
||||
$status = LadestationAdapter::dekodiereStatus(
|
||||
LadestationAdapter::GO_E_GEMINI,
|
||||
json_encode($daten, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
|
||||
self::assertSame(0, $status['Sollstrom_A']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider steuerFaelle
|
||||
* @param array<string, string> $konfiguration
|
||||
@@ -180,6 +198,13 @@ final class LadestationAdapterTest extends TestCase
|
||||
}
|
||||
$nrg[11] = $leistung;
|
||||
|
||||
return json_encode(['car' => $status, 'nrg' => $nrg], JSON_THROW_ON_ERROR);
|
||||
return json_encode([
|
||||
'car' => $status,
|
||||
'nrg' => $nrg,
|
||||
'amp' => 16,
|
||||
'ama' => 16,
|
||||
'alw' => true,
|
||||
'frc' => 2,
|
||||
], JSON_THROW_ON_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,4 +104,32 @@ final class LadestationStandAloneModulstrukturTest extends TestCase
|
||||
self::assertStringContainsString('PHASENERKENNUNGSSTROM = 6', $modul);
|
||||
self::assertStringContainsString('UnregisterVariable($ident)', $modul);
|
||||
}
|
||||
|
||||
public function testMeldezyklusSendetDenBereitsGelesenenZustandOhneZusaetzlichenHttpAbruf(): void
|
||||
{
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
self::assertSame(1, preg_match(
|
||||
"/case 'Melden':(?<block>.*?)case 'ManagerdatenEmpfangen':/s",
|
||||
$modul,
|
||||
$treffer
|
||||
));
|
||||
self::assertStringContainsString('$this->sendeVerbraucherdaten();', $treffer['block']);
|
||||
self::assertStringNotContainsString('$this->aktualisiere(', $treffer['block']);
|
||||
}
|
||||
|
||||
public function testVomGeraetBestaetigterSollstromWirdFuerWiederholungVerwendet(): void
|
||||
{
|
||||
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||
|
||||
self::assertStringContainsString("\$rohstatus['Sollstrom_A']", $modul);
|
||||
self::assertStringContainsString(
|
||||
"WriteAttributeInteger('LetzterGesetzterStrom', \$geraeteSollstrom)",
|
||||
$modul
|
||||
);
|
||||
self::assertStringContainsString("RegisterAttributeInteger('GeraeteMaximalstrom', 32)", $modul);
|
||||
self::assertStringContainsString(
|
||||
"WriteAttributeInteger('GeraeteMaximalstrom', (int) \$rohstatus['Maximalstrom_A'])",
|
||||
$modul
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,4 +380,25 @@ final class ManagerModulstrukturTest extends TestCase
|
||||
self::assertStringContainsString('VerbraucherdatenEmpfangen(array $daten)', $inhalt);
|
||||
self::assertStringContainsString("'ManagerdatenEmpfangen'", $inhalt);
|
||||
}
|
||||
|
||||
public function testVerbrauchermeldungPlantRegelungOhneSynchronenRueckruf(): void
|
||||
{
|
||||
$inhalt = (string) file_get_contents(__DIR__ . '/../Manager/module.php');
|
||||
self::assertStringContainsString(
|
||||
"RegisterTimer(\n 'RegelungVerzoegert'",
|
||||
$inhalt
|
||||
);
|
||||
self::assertStringContainsString("case 'RegelnVerzoegert':", $inhalt);
|
||||
self::assertSame(1, preg_match(
|
||||
'/public function VerbraucherdatenEmpfangen\(array \$daten\): void(?<block>.*?)'
|
||||
. 'private function aktualisiereVerbraucherEnergie/s',
|
||||
$inhalt,
|
||||
$treffer
|
||||
));
|
||||
self::assertStringContainsString(
|
||||
"SetTimerInterval('RegelungVerzoegert', 100)",
|
||||
$treffer['block']
|
||||
);
|
||||
self::assertStringNotContainsString('$this->regeln(false);', $treffer['block']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user