This commit is contained in:
@@ -15,6 +15,8 @@ Alle wesentlichen Aenderungen an Enelix EMS werden in dieser Datei dokumentiert.
|
|||||||
|
|
||||||
### Beta-Aenderungen
|
### Beta-Aenderungen
|
||||||
|
|
||||||
|
- Ladestationen halten beim Aktivieren und Umschalten von Solarladen den bisherigen Strom bis zur neuen Manager-Vorgabe; die Stand-alone-Phasenprobe verwendet nur noch 6 A.
|
||||||
|
- Fahrzeugstatus ist bei beiden Ladestationsvarianten eine Diagnosevariable, Ist- und Sollleistung gehoeren zu den optionalen Visualisierungseinstellungen.
|
||||||
- Stufenlose Leistungsbereiche fuer Batteriespeicher.
|
- Stufenlose Leistungsbereiche fuer Batteriespeicher.
|
||||||
- Ladefreigabe neuer Ladestationsinstanzen standardmaessig aktiviert.
|
- Ladefreigabe neuer Ladestationsinstanzen standardmaessig aktiviert.
|
||||||
- Stand-alone-Ladestationen erkennen nach einer einstellbaren Beobachtungszeit den niedrigeren Fahrzeug-Maximalstrom und begrenzen ihr Leistungsangebot ohne Ladeunterbruch.
|
- Stand-alone-Ladestationen erkennen nach einer einstellbaren Beobachtungszeit den niedrigeren Fahrzeug-Maximalstrom und begrenzen ihr Leistungsangebot ohne Ladeunterbruch.
|
||||||
|
|||||||
+118
-58
@@ -28,17 +28,17 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
private const STATUS_GATEWAY_GETRENNT = 202;
|
private const STATUS_GATEWAY_GETRENNT = 202;
|
||||||
private const STATUS_WARTET_AUF_DATEN = 203;
|
private const STATUS_WARTET_AUF_DATEN = 203;
|
||||||
private const STATUS_LADEFEHLER = 204;
|
private const STATUS_LADEFEHLER = 204;
|
||||||
|
private const REGELUEBERGANG_TIMEOUT_MS = 2000;
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
private const DIAGNOSE_VARIABLEN = [
|
private const DIAGNOSE_VARIABLEN = [
|
||||||
'Istleistung',
|
|
||||||
'Leistungsquelle',
|
'Leistungsquelle',
|
||||||
'Sollleistung',
|
|
||||||
'SollwertGueltig',
|
'SollwertGueltig',
|
||||||
'Verfuegbar',
|
'Verfuegbar',
|
||||||
'AenderungMoeglich',
|
'AenderungMoeglich',
|
||||||
'Stoerung',
|
'Stoerung',
|
||||||
'Stoertext',
|
'Stoertext',
|
||||||
|
'Fahrzeugstatus',
|
||||||
'GatewayVerbunden',
|
'GatewayVerbunden',
|
||||||
'ApiMaximalstrom',
|
'ApiMaximalstrom',
|
||||||
'EaseeAktiviert',
|
'EaseeAktiviert',
|
||||||
@@ -75,7 +75,6 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
'~Switch',
|
'~Switch',
|
||||||
110
|
110
|
||||||
);
|
);
|
||||||
$this->RegisterVariableInteger('Fahrzeugstatus', 'Fahrzeugstatus', '', 120);
|
|
||||||
$this->RegisterVariableFloat('Ladestrom', 'Ladestrom', '', 130);
|
$this->RegisterVariableFloat('Ladestrom', 'Ladestrom', '', 130);
|
||||||
$this->RegisterVariableInteger('Phasenzahl', 'Phasenzahl', '', 140);
|
$this->RegisterVariableInteger('Phasenzahl', 'Phasenzahl', '', 140);
|
||||||
|
|
||||||
@@ -113,6 +112,7 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
$this->RegisterAttributeBoolean('LadestartFuerVerbindungGesendet', false);
|
$this->RegisterAttributeBoolean('LadestartFuerVerbindungGesendet', false);
|
||||||
$this->RegisterAttributeString('LetzterGeraetebefehl', '');
|
$this->RegisterAttributeString('LetzterGeraetebefehl', '');
|
||||||
$this->RegisterAttributeString('LetzterStartbefehl', '');
|
$this->RegisterAttributeString('LetzterStartbefehl', '');
|
||||||
|
$this->RegisterAttributeBoolean('RegeluebergangAktiv', false);
|
||||||
|
|
||||||
$this->RegisterTimer(
|
$this->RegisterTimer(
|
||||||
'Meldezyklus',
|
'Meldezyklus',
|
||||||
@@ -129,6 +129,11 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
0,
|
0,
|
||||||
"IPS_RequestAction(\$_IPS['TARGET'], 'VorgabeTimeout', false);"
|
"IPS_RequestAction(\$_IPS['TARGET'], 'VorgabeTimeout', false);"
|
||||||
);
|
);
|
||||||
|
$this->RegisterTimer(
|
||||||
|
'RegeluebergangTimeout',
|
||||||
|
0,
|
||||||
|
"IPS_RequestAction(\$_IPS['TARGET'], 'RegeluebergangTimeout', false);"
|
||||||
|
);
|
||||||
|
|
||||||
$this->ConnectParent(self::EASEE_GATEWAY_MODULE_ID);
|
$this->ConnectParent(self::EASEE_GATEWAY_MODULE_ID);
|
||||||
}
|
}
|
||||||
@@ -142,6 +147,7 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
$this->WriteAttributeBoolean('GatewayVerbunden', false);
|
$this->WriteAttributeBoolean('GatewayVerbunden', false);
|
||||||
$this->WriteAttributeInteger('LetzterGesetzterStrom', -1);
|
$this->WriteAttributeInteger('LetzterGesetzterStrom', -1);
|
||||||
$this->WriteAttributeBoolean('LadestartFuerVerbindungGesendet', false);
|
$this->WriteAttributeBoolean('LadestartFuerVerbindungGesendet', false);
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->pruefeKonfiguration();
|
$this->pruefeKonfiguration();
|
||||||
@@ -167,17 +173,27 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
{
|
{
|
||||||
switch ($ident) {
|
switch ($ident) {
|
||||||
case 'Aktiv':
|
case 'Aktiv':
|
||||||
$this->SetValue('Aktiv', (bool) $wert);
|
$aktiv = (bool) $wert;
|
||||||
if (!(bool) $wert) {
|
$this->SetValue('Aktiv', $aktiv);
|
||||||
|
if ($aktiv) {
|
||||||
|
$this->starteRegeluebergang();
|
||||||
|
} else {
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
$this->setzeZustand('SollwertGueltig', false);
|
$this->setzeZustand('SollwertGueltig', false);
|
||||||
}
|
}
|
||||||
$this->aktualisiere(true);
|
$this->aktualisiere(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'Ladefreigabe':
|
case 'Ladefreigabe':
|
||||||
$this->WriteAttributeBoolean('ZustandLadefreigabe', (bool) $wert);
|
$ladefreigabe = (bool) $wert;
|
||||||
$this->setzeSichtbareVariable('Ladefreigabe', (bool) $wert);
|
$this->WriteAttributeBoolean('ZustandLadefreigabe', $ladefreigabe);
|
||||||
|
$this->setzeSichtbareVariable('Ladefreigabe', $ladefreigabe);
|
||||||
|
if ($ladefreigabe) {
|
||||||
|
$this->starteRegeluebergang();
|
||||||
|
} else {
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
$this->setzeZustand('SollwertGueltig', false);
|
$this->setzeZustand('SollwertGueltig', false);
|
||||||
|
}
|
||||||
$this->aktualisiere(true);
|
$this->aktualisiere(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -185,9 +201,11 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
$solarladen = EaseeLadestatus::solarladenErzwungen(
|
$solarladen = EaseeLadestatus::solarladenErzwungen(
|
||||||
$this->ReadPropertyInteger('Betriebsmodus')
|
$this->ReadPropertyInteger('Betriebsmodus')
|
||||||
) ? true : (bool) $wert;
|
) ? true : (bool) $wert;
|
||||||
|
if ($solarladen !== $this->ReadAttributeBoolean('ZustandSolarladen')) {
|
||||||
|
$this->starteRegeluebergang();
|
||||||
|
}
|
||||||
$this->WriteAttributeBoolean('ZustandSolarladen', $solarladen);
|
$this->WriteAttributeBoolean('ZustandSolarladen', $solarladen);
|
||||||
$this->setzeSichtbareVariable('Solarladen', $solarladen);
|
$this->setzeSichtbareVariable('Solarladen', $solarladen);
|
||||||
$this->setzeZustand('SollwertGueltig', false);
|
|
||||||
$this->aktualisiere(true);
|
$this->aktualisiere(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -201,6 +219,11 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
$this->aktualisiere(true);
|
$this->aktualisiere(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 'RegeluebergangTimeout':
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
|
$this->aktualisiere(true);
|
||||||
|
return;
|
||||||
|
|
||||||
case 'Melden':
|
case 'Melden':
|
||||||
if ((bool) $wert) {
|
if ((bool) $wert) {
|
||||||
$this->SetTimerInterval('RueckmeldungVerzoegert', 0);
|
$this->SetTimerInterval('RueckmeldungVerzoegert', 0);
|
||||||
@@ -288,7 +311,7 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->WriteAttributeString('Betriebsart', $daten['Betriebsart']);
|
$this->WriteAttributeString('Betriebsart', $daten['Betriebsart']);
|
||||||
$this->aktualisiere(false);
|
$this->aktualisiere(false, false);
|
||||||
$sollleistung = $daten['Sollleistung_W'];
|
$sollleistung = $daten['Sollleistung_W'];
|
||||||
if ($sollleistung === null) {
|
if ($sollleistung === null) {
|
||||||
if (
|
if (
|
||||||
@@ -311,6 +334,7 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
$this->WriteAttributeInteger('LetzteManagerID', $managerID);
|
$this->WriteAttributeInteger('LetzteManagerID', $managerID);
|
||||||
$this->WriteAttributeInteger('LetzteVorgabeZeit', time());
|
$this->WriteAttributeInteger('LetzteVorgabeZeit', time());
|
||||||
$this->setzeZustand('Sollleistung', $sollleistung);
|
$this->setzeZustand('Sollleistung', $sollleistung);
|
||||||
@@ -405,7 +429,10 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
$this->WriteAttributeInteger('LetzteBeobachtung', $zeitpunkt);
|
$this->WriteAttributeInteger('LetzteBeobachtung', $zeitpunkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function aktualisiere(bool $meldungPlanen): void
|
private function aktualisiere(
|
||||||
|
bool $meldungPlanen,
|
||||||
|
bool $steuerungAusfuehren = true
|
||||||
|
): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$status = EaseeLadestatus::ausBeobachtungen(
|
$status = EaseeLadestatus::ausBeobachtungen(
|
||||||
@@ -493,12 +520,21 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
}
|
}
|
||||||
$this->setzeStoerung($stoertext);
|
$this->setzeStoerung($stoertext);
|
||||||
|
|
||||||
|
$regeluebergangAktiv = (bool) $this->GetValue('Aktiv')
|
||||||
|
&& $this->ReadAttributeBoolean('ZustandLadefreigabe')
|
||||||
|
&& $steuerbar
|
||||||
|
&& $status['FahrzeugVerbunden']
|
||||||
|
&& !$status['FahrzeugGeladen']
|
||||||
|
&& $this->ReadAttributeBoolean('RegeluebergangAktiv');
|
||||||
if ($gatewayVerbunden && $status['StatusGueltig']) {
|
if ($gatewayVerbunden && $status['StatusGueltig']) {
|
||||||
|
$sollleistung = $this->bestimmeWirksameSollleistung($angebot);
|
||||||
|
if ($steuerungAusfuehren && !$regeluebergangAktiv) {
|
||||||
$this->setzeLadestrom(
|
$this->setzeLadestrom(
|
||||||
$this->bestimmeWirksameSollleistung($angebot),
|
$sollleistung,
|
||||||
$regelPhasenzahl,
|
$regelPhasenzahl,
|
||||||
$status['Fahrzeugstatus'] === 2
|
$status['Fahrzeugstatus'] === 2
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->WriteAttributeInteger('LetzterGesetzterStrom', -1);
|
$this->WriteAttributeInteger('LetzterGesetzterStrom', -1);
|
||||||
}
|
}
|
||||||
@@ -797,6 +833,23 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
return is_array($zuordnung) ? $zuordnung : [];
|
return is_array($zuordnung) ? $zuordnung : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function starteRegeluebergang(): void
|
||||||
|
{
|
||||||
|
if ($this->zugeordneteManagerIDs() === []) {
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->WriteAttributeBoolean('RegeluebergangAktiv', true);
|
||||||
|
$this->SetTimerInterval('RegeluebergangTimeout', self::REGELUEBERGANG_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function beendeRegeluebergang(): void
|
||||||
|
{
|
||||||
|
$this->WriteAttributeBoolean('RegeluebergangAktiv', false);
|
||||||
|
$this->SetTimerInterval('RegeluebergangTimeout', 0);
|
||||||
|
}
|
||||||
|
|
||||||
private function pruefeKonfiguration(): void
|
private function pruefeKonfiguration(): void
|
||||||
{
|
{
|
||||||
foreach (['PrioritaetPV', 'PrioritaetPeak'] as $property) {
|
foreach (['PrioritaetPV', 'PrioritaetPeak'] as $property) {
|
||||||
@@ -857,95 +910,63 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
|
|
||||||
private function aktualisiereVariablen(): void
|
private function aktualisiereVariablen(): void
|
||||||
{
|
{
|
||||||
if ($this->ReadPropertyBoolean('EinstellungenInVisu')) {
|
|
||||||
$this->RegisterVariableBoolean(
|
|
||||||
'Ladefreigabe',
|
|
||||||
'Ladefreigabe',
|
|
||||||
'~Switch',
|
|
||||||
150
|
|
||||||
);
|
|
||||||
$this->RegisterVariableBoolean(
|
|
||||||
'Solarladen',
|
|
||||||
'Solarladen',
|
|
||||||
'~Switch',
|
|
||||||
160
|
|
||||||
);
|
|
||||||
$this->EnableAction('Ladefreigabe');
|
|
||||||
$this->EnableAction('Solarladen');
|
|
||||||
$this->SetValue(
|
|
||||||
'Ladefreigabe',
|
|
||||||
$this->ReadAttributeBoolean('ZustandLadefreigabe')
|
|
||||||
);
|
|
||||||
$this->SetValue(
|
|
||||||
'Solarladen',
|
|
||||||
$this->ReadAttributeBoolean('ZustandSolarladen')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->entferneVariable('Ladefreigabe');
|
|
||||||
$this->entferneVariable('Solarladen');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->ReadPropertyBoolean('DiagnosevariablenAnzeigen')) {
|
if ($this->ReadPropertyBoolean('DiagnosevariablenAnzeigen')) {
|
||||||
$this->registriereVerbraucherDiagnose();
|
$this->registriereVerbraucherDiagnose();
|
||||||
|
$this->RegisterVariableInteger('Fahrzeugstatus', 'Fahrzeugstatus', '', 200);
|
||||||
$this->RegisterVariableBoolean(
|
$this->RegisterVariableBoolean(
|
||||||
'GatewayVerbunden',
|
'GatewayVerbunden',
|
||||||
'Easee Gateway verbunden',
|
'Easee Gateway verbunden',
|
||||||
'~Switch',
|
'~Switch',
|
||||||
200
|
|
||||||
);
|
|
||||||
$this->RegisterVariableInteger(
|
|
||||||
'ApiMaximalstrom',
|
|
||||||
'API-Maximalstrom',
|
|
||||||
'',
|
|
||||||
210
|
210
|
||||||
);
|
);
|
||||||
|
$this->RegisterVariableInteger('ApiMaximalstrom', 'API-Maximalstrom', '', 220);
|
||||||
$this->RegisterVariableBoolean(
|
$this->RegisterVariableBoolean(
|
||||||
'EaseeAktiviert',
|
'EaseeAktiviert',
|
||||||
'Easee aktiviert',
|
'Easee aktiviert',
|
||||||
'~Switch',
|
'~Switch',
|
||||||
220
|
230
|
||||||
);
|
);
|
||||||
$this->RegisterVariableBoolean(
|
$this->RegisterVariableBoolean(
|
||||||
'AutorisierungErforderlich',
|
'AutorisierungErforderlich',
|
||||||
'Autorisierung erforderlich',
|
'Autorisierung erforderlich',
|
||||||
'~Switch',
|
'~Switch',
|
||||||
230
|
240
|
||||||
);
|
);
|
||||||
$this->RegisterVariableBoolean(
|
$this->RegisterVariableBoolean(
|
||||||
'RemoteStartErforderlich',
|
'RemoteStartErforderlich',
|
||||||
'Remote-Start erforderlich',
|
'Remote-Start erforderlich',
|
||||||
'~Switch',
|
'~Switch',
|
||||||
240
|
250
|
||||||
);
|
);
|
||||||
$this->RegisterVariableBoolean(
|
$this->RegisterVariableBoolean(
|
||||||
'SmartCharging',
|
'SmartCharging',
|
||||||
'Easee Smart Charging',
|
'Easee Smart Charging',
|
||||||
'~Switch',
|
'~Switch',
|
||||||
250
|
260
|
||||||
);
|
);
|
||||||
$this->RegisterVariableInteger(
|
$this->RegisterVariableInteger(
|
||||||
'GrundKeinLadestrom',
|
'GrundKeinLadestrom',
|
||||||
'Grund kein Ladestrom',
|
'Grund kein Ladestrom',
|
||||||
'',
|
'',
|
||||||
260
|
|
||||||
);
|
|
||||||
$this->RegisterVariableString(
|
|
||||||
'LetzterGeraetebefehl',
|
|
||||||
'Letzter Geraetebefehl',
|
|
||||||
'',
|
|
||||||
270
|
270
|
||||||
);
|
);
|
||||||
|
$this->RegisterVariableString(
|
||||||
|
'LetzterGeraetebefehl',
|
||||||
|
'Letzter Geraetebefehl',
|
||||||
|
'',
|
||||||
|
280
|
||||||
|
);
|
||||||
$this->RegisterVariableString(
|
$this->RegisterVariableString(
|
||||||
'LetzterStartbefehl',
|
'LetzterStartbefehl',
|
||||||
'Letzter Startbefehl',
|
'Letzter Startbefehl',
|
||||||
'',
|
'',
|
||||||
280
|
290
|
||||||
);
|
);
|
||||||
$this->RegisterVariableString(
|
$this->RegisterVariableString(
|
||||||
'LeistungsangebotDiagnose',
|
'LeistungsangebotDiagnose',
|
||||||
'Leistungsangebot',
|
'Leistungsangebot',
|
||||||
'',
|
'',
|
||||||
290
|
300
|
||||||
);
|
);
|
||||||
$this->SetValue(
|
$this->SetValue(
|
||||||
'LeistungsangebotDiagnose',
|
'LeistungsangebotDiagnose',
|
||||||
@@ -983,6 +1004,40 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
$this->entferneVariable($ident);
|
$this->entferneVariable($ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->ReadPropertyBoolean('EinstellungenInVisu')) {
|
||||||
|
$this->RegisterVariableBoolean(
|
||||||
|
'Ladefreigabe',
|
||||||
|
'Ladefreigabe',
|
||||||
|
'~Switch',
|
||||||
|
150
|
||||||
|
);
|
||||||
|
$this->RegisterVariableBoolean(
|
||||||
|
'Solarladen',
|
||||||
|
'Solarladen',
|
||||||
|
'~Switch',
|
||||||
|
160
|
||||||
|
);
|
||||||
|
$this->RegisterVariableFloat('Istleistung', 'Istleistung', '', 170);
|
||||||
|
$this->RegisterVariableInteger('Sollleistung', 'Sollleistung', '', 180);
|
||||||
|
$this->EnableAction('Ladefreigabe');
|
||||||
|
$this->EnableAction('Solarladen');
|
||||||
|
$this->SetValue(
|
||||||
|
'Ladefreigabe',
|
||||||
|
$this->ReadAttributeBoolean('ZustandLadefreigabe')
|
||||||
|
);
|
||||||
|
$this->SetValue(
|
||||||
|
'Solarladen',
|
||||||
|
$this->ReadAttributeBoolean('ZustandSolarladen')
|
||||||
|
);
|
||||||
|
$this->SetValue('Istleistung', $this->ReadAttributeFloat('ZustandIstleistung'));
|
||||||
|
$this->SetValue('Sollleistung', $this->ReadAttributeInteger('ZustandSollleistung'));
|
||||||
|
} else {
|
||||||
|
$this->entferneVariable('Ladefreigabe');
|
||||||
|
$this->entferneVariable('Solarladen');
|
||||||
|
$this->entferneVariable('Istleistung');
|
||||||
|
$this->entferneVariable('Sollleistung');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function entferneVariable(string $ident): void
|
private function entferneVariable(string $ident): void
|
||||||
@@ -1108,7 +1163,12 @@ class LadestationGateway extends IPSModule implements VerbraucherSchnittstelle
|
|||||||
|
|
||||||
private function deaktiviereTimer(): void
|
private function deaktiviereTimer(): void
|
||||||
{
|
{
|
||||||
foreach (['Meldezyklus', 'RueckmeldungVerzoegert', 'VorgabeTimeout'] as $timer) {
|
foreach ([
|
||||||
|
'Meldezyklus',
|
||||||
|
'RueckmeldungVerzoegert',
|
||||||
|
'VorgabeTimeout',
|
||||||
|
'RegeluebergangTimeout',
|
||||||
|
] as $timer) {
|
||||||
$this->SetTimerInterval($timer, 0);
|
$this->SetTimerInterval($timer, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,17 +23,18 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
private const STATUS_AKTIV = 102;
|
private const STATUS_AKTIV = 102;
|
||||||
private const STATUS_KONFIGURATION_UNGUELTIG = 201;
|
private const STATUS_KONFIGURATION_UNGUELTIG = 201;
|
||||||
private const STATUS_KOMMUNIKATIONSFEHLER = 202;
|
private const STATUS_KOMMUNIKATIONSFEHLER = 202;
|
||||||
|
private const REGELUEBERGANG_TIMEOUT_MS = 2000;
|
||||||
|
private const PHASENERKENNUNGSSTROM = 6;
|
||||||
|
|
||||||
/** @var list<string> */
|
/** @var list<string> */
|
||||||
private const DIAGNOSE_VARIABLEN = [
|
private const DIAGNOSE_VARIABLEN = [
|
||||||
'Istleistung',
|
|
||||||
'Leistungsquelle',
|
'Leistungsquelle',
|
||||||
'Sollleistung',
|
|
||||||
'SollwertGueltig',
|
'SollwertGueltig',
|
||||||
'Verfuegbar',
|
'Verfuegbar',
|
||||||
'AenderungMoeglich',
|
'AenderungMoeglich',
|
||||||
'Stoerung',
|
'Stoerung',
|
||||||
'Stoertext',
|
'Stoertext',
|
||||||
|
'Fahrzeugstatus',
|
||||||
'FahrzeugMaximalstrom',
|
'FahrzeugMaximalstrom',
|
||||||
'LetzterGeraetebefehl',
|
'LetzterGeraetebefehl',
|
||||||
'LeistungsangebotDiagnose',
|
'LeistungsangebotDiagnose',
|
||||||
@@ -67,7 +68,6 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
|
|
||||||
$this->RegisterVariableBoolean('FahrzeugVerbunden', 'Fahrzeug verbunden', '~Switch', 100);
|
$this->RegisterVariableBoolean('FahrzeugVerbunden', 'Fahrzeug verbunden', '~Switch', 100);
|
||||||
$this->RegisterVariableBoolean('FahrzeugGeladen', 'Fahrzeug geladen', '~Switch', 110);
|
$this->RegisterVariableBoolean('FahrzeugGeladen', 'Fahrzeug geladen', '~Switch', 110);
|
||||||
$this->RegisterVariableInteger('Fahrzeugstatus', 'Fahrzeugstatus', '', 120);
|
|
||||||
$this->RegisterVariableFloat('Ladestrom', 'Ladestrom', '', 130);
|
$this->RegisterVariableFloat('Ladestrom', 'Ladestrom', '', 130);
|
||||||
$this->RegisterVariableInteger('Phasenzahl', 'Phasenzahl', '', 140);
|
$this->RegisterVariableInteger('Phasenzahl', 'Phasenzahl', '', 140);
|
||||||
|
|
||||||
@@ -103,6 +103,7 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
$this->RegisterAttributeInteger('ErkannterMaximalstrom', 32);
|
$this->RegisterAttributeInteger('ErkannterMaximalstrom', 32);
|
||||||
$this->RegisterAttributeInteger('FahrzeugstromKandidat', 0);
|
$this->RegisterAttributeInteger('FahrzeugstromKandidat', 0);
|
||||||
$this->RegisterAttributeInteger('FahrzeugstromKandidatSeit', 0);
|
$this->RegisterAttributeInteger('FahrzeugstromKandidatSeit', 0);
|
||||||
|
$this->RegisterAttributeBoolean('RegeluebergangAktiv', false);
|
||||||
|
|
||||||
$this->RegisterTimer(
|
$this->RegisterTimer(
|
||||||
'Statuszyklus',
|
'Statuszyklus',
|
||||||
@@ -124,6 +125,11 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
0,
|
0,
|
||||||
"IPS_RequestAction(\$_IPS['TARGET'], 'VorgabeTimeout', false);"
|
"IPS_RequestAction(\$_IPS['TARGET'], 'VorgabeTimeout', false);"
|
||||||
);
|
);
|
||||||
|
$this->RegisterTimer(
|
||||||
|
'RegeluebergangTimeout',
|
||||||
|
0,
|
||||||
|
"IPS_RequestAction(\$_IPS['TARGET'], 'RegeluebergangTimeout', false);"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ApplyChanges(): void
|
public function ApplyChanges(): void
|
||||||
@@ -154,6 +160,7 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
$this->ReadPropertyInteger('MaximalerLadestrom')
|
$this->ReadPropertyInteger('MaximalerLadestrom')
|
||||||
);
|
);
|
||||||
$this->setzeFahrzeugstromKandidatZurueck();
|
$this->setzeFahrzeugstromKandidatZurueck();
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->pruefeKonfiguration();
|
$this->pruefeKonfiguration();
|
||||||
@@ -176,18 +183,37 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
{
|
{
|
||||||
switch ($ident) {
|
switch ($ident) {
|
||||||
case 'Aktiv':
|
case 'Aktiv':
|
||||||
$this->SetValue('Aktiv', (bool) $wert);
|
$aktiv = (bool) $wert;
|
||||||
if (!(bool) $wert) {
|
$this->SetValue('Aktiv', $aktiv);
|
||||||
|
if ($aktiv) {
|
||||||
|
$this->starteRegeluebergang();
|
||||||
|
} else {
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
$this->setzeZustand('SollwertGueltig', false);
|
$this->setzeZustand('SollwertGueltig', false);
|
||||||
}
|
}
|
||||||
$this->aktualisiere(true);
|
$this->aktualisiere(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'Ladefreigabe':
|
case 'Ladefreigabe':
|
||||||
case 'Solarladen':
|
$ladefreigabe = (bool) $wert;
|
||||||
$this->WriteAttributeBoolean('Zustand' . $ident, (bool) $wert);
|
$this->WriteAttributeBoolean('ZustandLadefreigabe', $ladefreigabe);
|
||||||
$this->setzeSichtbareVariable($ident, (bool) $wert);
|
$this->setzeSichtbareVariable('Ladefreigabe', $ladefreigabe);
|
||||||
|
if ($ladefreigabe) {
|
||||||
|
$this->starteRegeluebergang();
|
||||||
|
} else {
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
$this->setzeZustand('SollwertGueltig', false);
|
$this->setzeZustand('SollwertGueltig', false);
|
||||||
|
}
|
||||||
|
$this->aktualisiere(true);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 'Solarladen':
|
||||||
|
$solarladen = (bool) $wert;
|
||||||
|
if ($solarladen !== $this->ReadAttributeBoolean('ZustandSolarladen')) {
|
||||||
|
$this->starteRegeluebergang();
|
||||||
|
}
|
||||||
|
$this->WriteAttributeBoolean('ZustandSolarladen', $solarladen);
|
||||||
|
$this->setzeSichtbareVariable('Solarladen', $solarladen);
|
||||||
$this->aktualisiere(true);
|
$this->aktualisiere(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -201,6 +227,11 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
$this->aktualisiere(true);
|
$this->aktualisiere(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 'RegeluebergangTimeout':
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
|
$this->aktualisiere(true);
|
||||||
|
return;
|
||||||
|
|
||||||
case 'Melden':
|
case 'Melden':
|
||||||
if ((bool) $wert) {
|
if ((bool) $wert) {
|
||||||
$this->SetTimerInterval('RueckmeldungVerzoegert', 0);
|
$this->SetTimerInterval('RueckmeldungVerzoegert', 0);
|
||||||
@@ -238,7 +269,7 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->WriteAttributeString('Betriebsart', $daten['Betriebsart']);
|
$this->WriteAttributeString('Betriebsart', $daten['Betriebsart']);
|
||||||
$this->aktualisiere(false, false);
|
$this->aktualisiere(false, false, false);
|
||||||
$sollleistung = $daten['Sollleistung_W'];
|
$sollleistung = $daten['Sollleistung_W'];
|
||||||
if ($sollleistung === null) {
|
if ($sollleistung === null) {
|
||||||
if ((bool) $this->leseZustand('SollwertGueltig')
|
if ((bool) $this->leseZustand('SollwertGueltig')
|
||||||
@@ -256,6 +287,7 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
$this->WriteAttributeInteger('LetzteManagerID', $managerID);
|
$this->WriteAttributeInteger('LetzteManagerID', $managerID);
|
||||||
$this->WriteAttributeInteger('LetzteVorgabeZeit', time());
|
$this->WriteAttributeInteger('LetzteVorgabeZeit', time());
|
||||||
$this->setzeZustand('Sollleistung', $sollleistung);
|
$this->setzeZustand('Sollleistung', $sollleistung);
|
||||||
@@ -265,7 +297,11 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
$this->SetTimerInterval('RueckmeldungVerzoegert', 100);
|
$this->SetTimerInterval('RueckmeldungVerzoegert', 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function aktualisiere(bool $meldungPlanen, bool $statusLesen = true): void
|
private function aktualisiere(
|
||||||
|
bool $meldungPlanen,
|
||||||
|
bool $statusLesen = true,
|
||||||
|
bool $steuerungAusfuehren = true
|
||||||
|
): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if ($statusLesen) {
|
if ($statusLesen) {
|
||||||
@@ -346,12 +382,17 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
$this->setzeZustand('AenderungMoeglich', $verfuegbar && count($angebot) > 1);
|
$this->setzeZustand('AenderungMoeglich', $verfuegbar && count($angebot) > 1);
|
||||||
|
|
||||||
$sollleistung = $this->bestimmeWirksameSollleistung($angebot);
|
$sollleistung = $this->bestimmeWirksameSollleistung($angebot);
|
||||||
if (!($aktiv
|
$phasenerkennungAktiv = $aktiv
|
||||||
&& $ladefreigabe
|
&& $ladefreigabe
|
||||||
&& $verbunden
|
&& $verbunden
|
||||||
&& !$geladen
|
&& !$geladen
|
||||||
&& $phasenzahl === LadestationRegler::PHASEN_UNBEKANNT
|
&& $phasenzahl === LadestationRegler::PHASEN_UNBEKANNT;
|
||||||
)) {
|
$regeluebergangAktiv = $aktiv
|
||||||
|
&& $ladefreigabe
|
||||||
|
&& $verbunden
|
||||||
|
&& !$geladen
|
||||||
|
&& $this->ReadAttributeBoolean('RegeluebergangAktiv');
|
||||||
|
if ($steuerungAusfuehren && !$phasenerkennungAktiv && !$regeluebergangAktiv) {
|
||||||
$this->setzeLadestrom($sollleistung);
|
$this->setzeLadestrom($sollleistung);
|
||||||
}
|
}
|
||||||
$this->setzeStoerung('');
|
$this->setzeStoerung('');
|
||||||
@@ -413,17 +454,16 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
) {
|
) {
|
||||||
$erkennungSeit = $this->ReadAttributeInteger('PhasenerkennungSeit');
|
$erkennungSeit = $this->ReadAttributeInteger('PhasenerkennungSeit');
|
||||||
if ($erkennungSeit <= 0) {
|
if ($erkennungSeit <= 0) {
|
||||||
$this->sendeLadestromAnGeraet(
|
$this->sendeLadestromAnGeraet(self::PHASENERKENNUNGSSTROM);
|
||||||
$this->ReadPropertyInteger('MaximalerLadestrom')
|
|
||||||
);
|
|
||||||
$erkennungSeit = time();
|
$erkennungSeit = time();
|
||||||
$this->WriteAttributeInteger('PhasenerkennungSeit', $erkennungSeit);
|
$this->WriteAttributeInteger('PhasenerkennungSeit', $erkennungSeit);
|
||||||
} elseif ((time() - $erkennungSeit)
|
} elseif ((time() - $erkennungSeit)
|
||||||
>= $this->ReadPropertyInteger('Phasenerkennungszeit')
|
>= $this->ReadPropertyInteger('Phasenerkennungszeit')
|
||||||
) {
|
) {
|
||||||
$bekanntePhasenzahl = $rohstatus['Istleistung_W'] > 7500.0
|
$bekanntePhasenzahl = LadestationRegler::erkennePhasenzahlAusLeistung(
|
||||||
? LadestationRegler::PHASEN_DREI
|
(float) $rohstatus['Istleistung_W'],
|
||||||
: LadestationRegler::PHASEN_EIN;
|
$this->ReadAttributeInteger('LetzterGesetzterStrom')
|
||||||
|
);
|
||||||
$this->WriteAttributeInteger('PhasenerkennungSeit', 0);
|
$this->WriteAttributeInteger('PhasenerkennungSeit', 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -819,6 +859,23 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
return is_array($zuordnung) ? $zuordnung : [];
|
return is_array($zuordnung) ? $zuordnung : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function starteRegeluebergang(): void
|
||||||
|
{
|
||||||
|
if ($this->zugeordneteManagerIDs() === []) {
|
||||||
|
$this->beendeRegeluebergang();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->WriteAttributeBoolean('RegeluebergangAktiv', true);
|
||||||
|
$this->SetTimerInterval('RegeluebergangTimeout', self::REGELUEBERGANG_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function beendeRegeluebergang(): void
|
||||||
|
{
|
||||||
|
$this->WriteAttributeBoolean('RegeluebergangAktiv', false);
|
||||||
|
$this->SetTimerInterval('RegeluebergangTimeout', 0);
|
||||||
|
}
|
||||||
|
|
||||||
private function pruefeKonfiguration(): void
|
private function pruefeKonfiguration(): void
|
||||||
{
|
{
|
||||||
foreach (['PrioritaetPV', 'PrioritaetPeak'] as $property) {
|
foreach (['PrioritaetPV', 'PrioritaetPeak'] as $property) {
|
||||||
@@ -882,27 +939,16 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
|
|
||||||
private function aktualisiereVariablen(): void
|
private function aktualisiereVariablen(): void
|
||||||
{
|
{
|
||||||
if ($this->ReadPropertyBoolean('EinstellungenInVisu')) {
|
|
||||||
$this->RegisterVariableBoolean('Ladefreigabe', 'Ladefreigabe', '~Switch', 150);
|
|
||||||
$this->RegisterVariableBoolean('Solarladen', 'Solarladen', '~Switch', 160);
|
|
||||||
$this->EnableAction('Ladefreigabe');
|
|
||||||
$this->EnableAction('Solarladen');
|
|
||||||
$this->SetValue('Ladefreigabe', $this->ReadAttributeBoolean('ZustandLadefreigabe'));
|
|
||||||
$this->SetValue('Solarladen', $this->ReadAttributeBoolean('ZustandSolarladen'));
|
|
||||||
} else {
|
|
||||||
$this->entferneVariable('Ladefreigabe');
|
|
||||||
$this->entferneVariable('Solarladen');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->ReadPropertyBoolean('DiagnosevariablenAnzeigen')) {
|
if ($this->ReadPropertyBoolean('DiagnosevariablenAnzeigen')) {
|
||||||
$this->registriereVerbraucherDiagnose();
|
$this->registriereVerbraucherDiagnose();
|
||||||
$this->RegisterVariableString('LetzterGeraetebefehl', 'Letzter Geraetebefehl', '', 200);
|
$this->RegisterVariableInteger('Fahrzeugstatus', 'Fahrzeugstatus', '', 200);
|
||||||
$this->RegisterVariableString('LeistungsangebotDiagnose', 'Leistungsangebot', '', 210);
|
$this->RegisterVariableString('LetzterGeraetebefehl', 'Letzter Geraetebefehl', '', 210);
|
||||||
|
$this->RegisterVariableString('LeistungsangebotDiagnose', 'Leistungsangebot', '', 220);
|
||||||
$this->RegisterVariableInteger(
|
$this->RegisterVariableInteger(
|
||||||
'FahrzeugMaximalstrom',
|
'FahrzeugMaximalstrom',
|
||||||
'Erkannter Fahrzeug-Maximalstrom',
|
'Erkannter Fahrzeug-Maximalstrom',
|
||||||
'',
|
'',
|
||||||
220
|
230
|
||||||
);
|
);
|
||||||
$this->SetValue(
|
$this->SetValue(
|
||||||
'FahrzeugMaximalstrom',
|
'FahrzeugMaximalstrom',
|
||||||
@@ -926,6 +972,24 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
$this->entferneVariable($ident);
|
$this->entferneVariable($ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->ReadPropertyBoolean('EinstellungenInVisu')) {
|
||||||
|
$this->RegisterVariableBoolean('Ladefreigabe', 'Ladefreigabe', '~Switch', 150);
|
||||||
|
$this->RegisterVariableBoolean('Solarladen', 'Solarladen', '~Switch', 160);
|
||||||
|
$this->RegisterVariableFloat('Istleistung', 'Istleistung', '', 170);
|
||||||
|
$this->RegisterVariableInteger('Sollleistung', 'Sollleistung', '', 180);
|
||||||
|
$this->EnableAction('Ladefreigabe');
|
||||||
|
$this->EnableAction('Solarladen');
|
||||||
|
$this->SetValue('Ladefreigabe', $this->ReadAttributeBoolean('ZustandLadefreigabe'));
|
||||||
|
$this->SetValue('Solarladen', $this->ReadAttributeBoolean('ZustandSolarladen'));
|
||||||
|
$this->SetValue('Istleistung', $this->ReadAttributeFloat('ZustandIstleistung'));
|
||||||
|
$this->SetValue('Sollleistung', $this->ReadAttributeInteger('ZustandSollleistung'));
|
||||||
|
} else {
|
||||||
|
$this->entferneVariable('Ladefreigabe');
|
||||||
|
$this->entferneVariable('Solarladen');
|
||||||
|
$this->entferneVariable('Istleistung');
|
||||||
|
$this->entferneVariable('Sollleistung');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function entferneVariable(string $ident): void
|
private function entferneVariable(string $ident): void
|
||||||
@@ -1033,7 +1097,13 @@ class LadestationStandAlone extends IPSModule implements VerbraucherSchnittstell
|
|||||||
|
|
||||||
private function deaktiviereTimer(): void
|
private function deaktiviereTimer(): void
|
||||||
{
|
{
|
||||||
foreach (['Statuszyklus', 'Meldezyklus', 'RueckmeldungVerzoegert', 'VorgabeTimeout'] as $timer) {
|
foreach ([
|
||||||
|
'Statuszyklus',
|
||||||
|
'Meldezyklus',
|
||||||
|
'RueckmeldungVerzoegert',
|
||||||
|
'VorgabeTimeout',
|
||||||
|
'RegeluebergangTimeout',
|
||||||
|
] as $timer) {
|
||||||
$this->SetTimerInterval($timer, 0);
|
$this->SetTimerInterval($timer, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,22 +50,22 @@ als ungueltig behandelt und ergeben bis zur gueltigen 1-/3-Phasenmeldung nur
|
|||||||
| `PrioritaetPeak` | Integer | `0` | Prioritaet im Peakbetrieb. |
|
| `PrioritaetPeak` | Integer | `0` | Prioritaet im Peakbetrieb. |
|
||||||
| `Meldeintervall` | Integer | `10 s` | Periodische Vollmeldung an den Manager. |
|
| `Meldeintervall` | Integer | `10 s` | Periodische Vollmeldung an den Manager. |
|
||||||
| `VorgabeTimeout` | Integer | `120 s` | Ablauf einer nicht erneuerten Manager-Vorgabe. |
|
| `VorgabeTimeout` | Integer | `120 s` | Ablauf einer nicht erneuerten Manager-Vorgabe. |
|
||||||
| `EinstellungenInVisu` | Boolean | `false` | Zeigt Ladefreigabe und Solarladen. |
|
| `EinstellungenInVisu` | Boolean | `false` | Zeigt Ladefreigabe, Solarladen, Istleistung und Sollleistung. |
|
||||||
| `DiagnosevariablenAnzeigen` | Boolean | `false` | Zeigt technische Diagnosewerte. |
|
| `DiagnosevariablenAnzeigen` | Boolean | `false` | Zeigt technische Diagnosewerte. |
|
||||||
| `LoggingEin` | Boolean | `false` | Aktiviert Debugmeldungen ohne Geheimnisse. |
|
| `LoggingEin` | Boolean | `false` | Aktiviert Debugmeldungen ohne Geheimnisse. |
|
||||||
|
|
||||||
## Variablen
|
## Variablen
|
||||||
|
|
||||||
Immer sichtbar sind `Aktiv`, `FahrzeugVerbunden`, `FahrzeugGeladen`,
|
Immer sichtbar sind `Aktiv`, `FahrzeugVerbunden`, `FahrzeugGeladen`,
|
||||||
`Fahrzeugstatus`, `Ladestrom` und `Phasenzahl`. Der normalisierte
|
`Ladestrom` und `Phasenzahl`. Mit `EinstellungenInVisu=true` erscheinen
|
||||||
Fahrzeugstatus ist `0` unbekannt, `1` getrennt, `2` wartet auf Start,
|
zusaetzlich `Ladefreigabe`, `Solarladen`, `Istleistung` und `Sollleistung`.
|
||||||
`3` laedt, `4` geladen oder `5` Fehler.
|
|
||||||
|
|
||||||
Optional sichtbar sind die gemeinsamen EMS-Diagnosewerte sowie
|
Mit `DiagnosevariablenAnzeigen=true` werden der numerische `Fahrzeugstatus`
|
||||||
|
und die gemeinsamen EMS-Diagnosewerte sowie
|
||||||
`GatewayVerbunden`, `ApiMaximalstrom`, `EaseeAktiviert`,
|
`GatewayVerbunden`, `ApiMaximalstrom`, `EaseeAktiviert`,
|
||||||
`AutorisierungErforderlich`, `RemoteStartErforderlich`, `SmartCharging`,
|
`AutorisierungErforderlich`, `RemoteStartErforderlich`, `SmartCharging`,
|
||||||
`GrundKeinLadestrom`, `LetzterGeraetebefehl`, `LetzterStartbefehl` und
|
`GrundKeinLadestrom`, `LetzterGeraetebefehl`, `LetzterStartbefehl` und
|
||||||
`LeistungsangebotDiagnose`. `GrundKeinLadestrom=55` bedeutet bei Easee, dass
|
`LeistungsangebotDiagnose` angezeigt. `GrundKeinLadestrom=55` bedeutet bei Easee, dass
|
||||||
die Autorisierung fehlt.
|
die Autorisierung fehlt.
|
||||||
|
|
||||||
## Regelung
|
## Regelung
|
||||||
@@ -83,6 +83,11 @@ Ladestation Stand-Alone:
|
|||||||
Die niedrigste Grenze aus Property, Observation `47` und Observation `104`
|
Die niedrigste Grenze aus Property, Observation `47` und Observation `104`
|
||||||
bestimmt den angebotenen Maximalstrom. Eine neue Observation berechnet das
|
bestimmt den angebotenen Maximalstrom. Eine neue Observation berechnet das
|
||||||
Angebot sofort neu und meldet die Aenderung kurz gebuendelt an den Manager.
|
Angebot sofort neu und meldet die Aenderung kurz gebuendelt an den Manager.
|
||||||
|
Beim Aktivieren oder Umschalten von Solarladen bleibt der bisherige
|
||||||
|
Geraetestrom bis zur neuen Manager-Vorgabe unveraendert. Ohne Managerantwort
|
||||||
|
greift nach zwei Sekunden das lokale Ersatzverhalten. Sicherheitsabschaltungen
|
||||||
|
werden nicht verzoegert.
|
||||||
|
|
||||||
Bei einer Gateway-Unterbrechung werden Fahrzeug- und Phasenstatus sofort
|
Bei einer Gateway-Unterbrechung werden Fahrzeug- und Phasenstatus sofort
|
||||||
verworfen; erst ein neuer aktueller Gateway-Zustand gibt die Regelung wieder
|
verworfen; erst ein neuer aktueller Gateway-Zustand gibt die Regelung wieder
|
||||||
frei. Die eigentliche Vorgabe wird als dynamischer Ladestrom mit `minutes=0`
|
frei. Die eigentliche Vorgabe wird als dynamischer Ladestrom mit `minutes=0`
|
||||||
|
|||||||
@@ -43,11 +43,11 @@ Die Auswertung folgt bewusst dem Verhalten der bisherigen Enelix-1-Ladestation:
|
|||||||
3. go-e meldet die drei Phasenstroeme einzeln. Sobald mindestens zwei Phasen
|
3. go-e meldet die drei Phasenstroeme einzeln. Sobald mindestens zwei Phasen
|
||||||
Strom fuehren, wird dreiphasiges Laden direkt erkannt.
|
Strom fuehren, wird dreiphasiges Laden direkt erkannt.
|
||||||
4. Sind beim Anstecken noch keine belastbaren Phasenwerte vorhanden, gibt das
|
4. Sind beim Anstecken noch keine belastbaren Phasenwerte vorhanden, gibt das
|
||||||
Modul zunaechst den konfigurierten Maximalstrom als Erkennungsstrom vor. Bis
|
Modul zunaechst nur den Mindeststrom von 6 A als Erkennungsstrom vor. Bis zur
|
||||||
zur abgeschlossenen Erkennung bleibt `Phasenzahl=0` und das EMS-Angebot
|
abgeschlossenen Erkennung bleibt `Phasenzahl=0` und das EMS-Angebot `[0]`.
|
||||||
`[0]`.
|
5. Nach `Phasenerkennungszeit` wird die gemessene Leistung relativ zum
|
||||||
5. Nach `Phasenerkennungszeit` gilt wie in Enelix 1: ueber 7500 W werden drei
|
angeforderten Erkennungsstrom ausgewertet. Dadurch lassen sich eine und drei
|
||||||
Phasen erkannt, andernfalls eine Phase. Die erkannte Phasenzahl bleibt bis
|
Phasen bereits bei 6 A unterscheiden. Die erkannte Phasenzahl bleibt bis
|
||||||
zum Ausstecken erhalten und kippt waehrend einer Ladepause nicht zurueck.
|
zum Ausstecken erhalten und kippt waehrend einer Ladepause nicht zurueck.
|
||||||
6. Der Ladestrom wird aus der Leistung mit `230 W/A` einphasig beziehungsweise
|
6. Der Ladestrom wird aus der Leistung mit `230 W/A` einphasig beziehungsweise
|
||||||
`684 W/A` dreiphasig berechnet.
|
`684 W/A` dreiphasig berechnet.
|
||||||
@@ -84,6 +84,12 @@ Die Leistungsstufen entsprechen Enelix 1: `230 W` pro Ampere einphasig und
|
|||||||
bei aktivem Solarladen mit `0 A`; bei ausgeschaltetem Solarladen verwendet es
|
bei aktivem Solarladen mit `0 A`; bei ausgeschaltetem Solarladen verwendet es
|
||||||
die maximale angebotene Leistung.
|
die maximale angebotene Leistung.
|
||||||
|
|
||||||
|
Beim Aktivieren oder Umschalten von Solarladen bleibt ein bereits gesetzter
|
||||||
|
Geraetestrom zunaechst unveraendert. Das neue Angebot wird zuerst an den
|
||||||
|
zugeordneten Manager gemeldet; dessen neue Vorgabe wird anschliessend direkt
|
||||||
|
uebernommen. Antwortet kein Manager, greift nach zwei Sekunden das lokale
|
||||||
|
Ersatzverhalten. Sicherheitsabschaltungen wirken weiterhin sofort.
|
||||||
|
|
||||||
Nach einer Leistungsaenderung wird die aktuelle Stufe fuer
|
Nach einer Leistungsaenderung wird die aktuelle Stufe fuer
|
||||||
`ZeitZwischenZustandswechseln` gehalten. Waehrend der
|
`ZeitZwischenZustandswechseln` gehalten. Waehrend der
|
||||||
`Mindesteinschaltdauer` bleiben positive Leistungsstufen regelbar, `0 W`
|
`Mindesteinschaltdauer` bleiben positive Leistungsstufen regelbar, `0 W`
|
||||||
@@ -115,7 +121,7 @@ gueltige Manager-Vorgabe und berechnet das Leistungsangebot sofort neu.
|
|||||||
| `PrioritaetPeak` | Integer | `0` | Prioritaet des Verbrauchers im Peakbetrieb. |
|
| `PrioritaetPeak` | Integer | `0` | Prioritaet des Verbrauchers im Peakbetrieb. |
|
||||||
| `Meldeintervall` | Integer | `10 s` | Intervall fuer die periodische Vollmeldung an zugeordnete Manager. |
|
| `Meldeintervall` | Integer | `10 s` | Intervall fuer die periodische Vollmeldung an zugeordnete Manager. |
|
||||||
| `VorgabeTimeout` | Integer | `120 s` | Gueltigkeitsdauer einer Manager-Vorgabe ohne Erneuerung. |
|
| `VorgabeTimeout` | Integer | `120 s` | Gueltigkeitsdauer einer Manager-Vorgabe ohne Erneuerung. |
|
||||||
| `EinstellungenInVisu` | Boolean | `false` | Blendet `Ladefreigabe` und `Solarladen` als bedienbare Variablen ein. |
|
| `EinstellungenInVisu` | Boolean | `false` | Blendet `Ladefreigabe`, `Solarladen`, `Istleistung` und `Sollleistung` ein. |
|
||||||
| `LoggingEin` | Boolean | `false` | Aktiviert das laufende Debug-Protokoll des Moduls. |
|
| `LoggingEin` | Boolean | `false` | Aktiviert das laufende Debug-Protokoll des Moduls. |
|
||||||
|
|
||||||
### Ladestation und Diagnose
|
### Ladestation und Diagnose
|
||||||
@@ -129,7 +135,7 @@ gueltige Manager-Vorgabe und berechnet das Leistungsangebot sofort neu.
|
|||||||
| `Benutzername` | String | leer | Benutzername fuer die Pico-API. |
|
| `Benutzername` | String | leer | Benutzername fuer die Pico-API. |
|
||||||
| `Passwort` | String | leer | Passwort fuer die Pico-API; im Formular als Passwortfeld dargestellt. |
|
| `Passwort` | String | leer | Passwort fuer die Pico-API; im Formular als Passwortfeld dargestellt. |
|
||||||
| `MaximalerLadestrom` | Integer | `16 A` | Obergrenze der angebotenen Ladestufen; zulaessig sind 6 bis 32 A. |
|
| `MaximalerLadestrom` | Integer | `16 A` | Obergrenze der angebotenen Ladestufen; zulaessig sind 6 bis 32 A. |
|
||||||
| `Phasenerkennungszeit` | Integer | `60 s` | Dauer der Maximalstrom-Probe vor der leistungsbasierten Phasenerkennung. |
|
| `Phasenerkennungszeit` | Integer | `60 s` | Dauer der 6-A-Probe vor der leistungsbasierten Phasenerkennung. |
|
||||||
| `FahrzeugstromErkennungszeit` | Integer | `90 s` | Zeit, die eine stabile Stromunterschreitung anliegen muss, bevor die Fahrzeuggrenze mit 2,5 A Reserve uebernommen wird. |
|
| `FahrzeugstromErkennungszeit` | Integer | `90 s` | Zeit, die eine stabile Stromunterschreitung anliegen muss, bevor die Fahrzeuggrenze mit 2,5 A Reserve uebernommen wird. |
|
||||||
| `ZeitZwischenZustandswechseln` | Integer | `1 min` | Mindestabstand zwischen zwei Leistungsaenderungen. |
|
| `ZeitZwischenZustandswechseln` | Integer | `1 min` | Mindestabstand zwischen zwei Leistungsaenderungen. |
|
||||||
| `Mindesteinschaltdauer` | Integer | `0 min` | Mindestdauer nach dem Einschalten, in der kein Abschalten auf 0 W angeboten wird. |
|
| `Mindesteinschaltdauer` | Integer | `0 min` | Mindestdauer nach dem Einschalten, in der kein Abschalten auf 0 W angeboten wird. |
|
||||||
@@ -152,22 +158,22 @@ Immer sichtbar:
|
|||||||
| `Aktiv` | Boolean / bedienbar | Lokale EMS-Freigabe; der Initialwert ist `false`. |
|
| `Aktiv` | Boolean / bedienbar | Lokale EMS-Freigabe; der Initialwert ist `false`. |
|
||||||
| `FahrzeugVerbunden` | Boolean / Anzeige | Zeigt, ob die API ein verbundenes Fahrzeug meldet. |
|
| `FahrzeugVerbunden` | Boolean / Anzeige | Zeigt, ob die API ein verbundenes Fahrzeug meldet. |
|
||||||
| `FahrzeugGeladen` | Boolean / Anzeige | Ergebnis der kompatiblen Enelix-1-Voll-Erkennung. |
|
| `FahrzeugGeladen` | Boolean / Anzeige | Ergebnis der kompatiblen Enelix-1-Voll-Erkennung. |
|
||||||
| `Fahrzeugstatus` | Integer / Anzeige | Normalisierter Status von `0` bis `4`. |
|
|
||||||
| `Ladestrom` | Float / Anzeige | Aus der gemessenen Leistung ermittelter Ladestrom in A. |
|
| `Ladestrom` | Float / Anzeige | Aus der gemessenen Leistung ermittelter Ladestrom in A. |
|
||||||
| `Phasenzahl` | Integer / Anzeige | `0` unbekannt, `1` einphasig oder `3` dreiphasig. |
|
| `Phasenzahl` | Integer / Anzeige | `0` unbekannt, `1` einphasig oder `3` dreiphasig. |
|
||||||
|
|
||||||
Nur mit `EinstellungenInVisu=true` sichtbar und bedienbar:
|
Nur mit `EinstellungenInVisu=true` sichtbar; Ladefreigabe und Solarladen sind bedienbar:
|
||||||
|
|
||||||
- `Ladefreigabe`
|
- `Ladefreigabe`
|
||||||
- `Solarladen`
|
- `Solarladen`
|
||||||
|
- `Istleistung`
|
||||||
|
- `Sollleistung`
|
||||||
|
|
||||||
Nur mit `DiagnosevariablenAnzeigen=true` sichtbar:
|
Nur mit `DiagnosevariablenAnzeigen=true` sichtbar:
|
||||||
|
|
||||||
| Ident | Beschreibung |
|
| Ident | Beschreibung |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `Istleistung` | Von der Ladestation gemessene Leistung in W. |
|
|
||||||
| `Leistungsquelle` | Immer `2` fuer eine gemessene Leistung. |
|
| `Leistungsquelle` | Immer `2` fuer eine gemessene Leistung. |
|
||||||
| `Sollleistung` | Letzte angenommene Manager-Vorgabe in W. |
|
| `Fahrzeugstatus` | Normalisierter Status von `0` bis `4`. |
|
||||||
| `SollwertGueltig` | Zeigt, ob die Vorgabe noch gueltig und im aktuellen Angebot enthalten ist. |
|
| `SollwertGueltig` | Zeigt, ob die Vorgabe noch gueltig und im aktuellen Angebot enthalten ist. |
|
||||||
| `Verfuegbar` | Zeigt, ob die Ladestation grundsaetzlich Leistung aufnehmen kann. |
|
| `Verfuegbar` | Zeigt, ob die Ladestation grundsaetzlich Leistung aufnehmen kann. |
|
||||||
| `AenderungMoeglich` | Zeigt, ob das aktuelle Angebot mehr als eine Leistungsstufe enthaelt. |
|
| `AenderungMoeglich` | Zeigt, ob das aktuelle Angebot mehr als eine Leistungsstufe enthaelt. |
|
||||||
@@ -253,8 +259,8 @@ niemals in Repository-Dateien, Skripte oder Screenshots.
|
|||||||
- Ohne Fahrzeug sind `FahrzeugVerbunden=false`, `Phasenzahl=0` und das
|
- Ohne Fahrzeug sind `FahrzeugVerbunden=false`, `Phasenzahl=0` und das
|
||||||
Leistungsangebot `[0]`.
|
Leistungsangebot `[0]`.
|
||||||
- Nach dem Anstecken wird das Fahrzeug erkannt und bei unbekannten Phasen
|
- Nach dem Anstecken wird das Fahrzeug erkannt und bei unbekannten Phasen
|
||||||
zunaechst der konfigurierte Maximalstrom zur Erkennung angefordert.
|
zunaechst der Mindeststrom von 6 A zur Erkennung angefordert.
|
||||||
- Nach der Erkennungszeit werden bis 7500 W eine Phase, darueber drei Phasen
|
- Nach der Erkennungszeit werden eine oder drei Phasen relativ zum Pruefstrom
|
||||||
gespeichert. Bei go-e koennen die einzelnen Phasenstroeme die Erkennung
|
gespeichert. Bei go-e koennen die einzelnen Phasenstroeme die Erkennung
|
||||||
bereits vorher abschliessen.
|
bereits vorher abschliessen.
|
||||||
- Die erkannte Phasenzahl bleibt bei einer anschliessenden Ladepause stabil.
|
- Die erkannte Phasenzahl bleibt bei einer anschliessenden Ladepause stabil.
|
||||||
@@ -298,7 +304,7 @@ URL, HTTP-Methode, Authentisierung und Steueraufrufe ohne reale Hardware
|
|||||||
geprueft.
|
geprueft.
|
||||||
|
|
||||||
Der Symcon-Funktionstest verwendet den internen `Testmodus` mit simulierten
|
Der Symcon-Funktionstest verwendet den internen `Testmodus` mit simulierten
|
||||||
API-Antworten. Er prueft alle drei Geraetevarianten, die Maximalstrom-Probe
|
API-Antworten. Er prueft alle drei Geraetevarianten, die Mindeststrom-Probe
|
||||||
beim Anstecken, stabile Phasen waehrend einer Ladepause, die Schaltsperren,
|
beim Anstecken, stabile Phasen waehrend einer Ladepause, die Schaltsperren,
|
||||||
Fahrzeugstrom-Erkennung, die Leistungsangebote in PV und Peak sowie die
|
Fahrzeugstrom-Erkennung, die Leistungsangebote in PV und Peak sowie die
|
||||||
Umschaltung ueber den `Solarladen`-Button.
|
Umschaltung ueber den `Solarladen`-Button.
|
||||||
|
|||||||
@@ -15,6 +15,22 @@ final class LadestationRegler
|
|||||||
private const LEISTUNG_PRO_AMPERE_EINPHASIG = 230;
|
private const LEISTUNG_PRO_AMPERE_EINPHASIG = 230;
|
||||||
private const LEISTUNG_PRO_AMPERE_DREIPHASIG = 684;
|
private const LEISTUNG_PRO_AMPERE_DREIPHASIG = 684;
|
||||||
|
|
||||||
|
public static function erkennePhasenzahlAusLeistung(
|
||||||
|
float $leistung,
|
||||||
|
int $angeforderterStrom
|
||||||
|
): int {
|
||||||
|
if (!is_finite($leistung) || $leistung < 0.0) {
|
||||||
|
throw new InvalidArgumentException('Istleistung muss endlich und darf nicht negativ sein.');
|
||||||
|
}
|
||||||
|
if ($angeforderterStrom < 6 || $angeforderterStrom > 32) {
|
||||||
|
throw new InvalidArgumentException('Erkennungsstrom muss zwischen 6 und 32 A liegen.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$trennleistung = 2 * self::LEISTUNG_PRO_AMPERE_EINPHASIG * $angeforderterStrom;
|
||||||
|
|
||||||
|
return $leistung > $trennleistung ? self::PHASEN_DREI : self::PHASEN_EIN;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Die Schwelle und der Zuschlag von 2.5 A stammen aus der Enelix-1-Ladestation.
|
* Die Schwelle und der Zuschlag von 2.5 A stammen aus der Enelix-1-Ladestation.
|
||||||
* Ein Ladeende wird erst nach zuvor gemessener Ladeleistung angenommen, damit
|
* Ein Ladeende wird erst nach zuvor gemessener Ladeleistung angenommen, damit
|
||||||
|
|||||||
@@ -70,6 +70,19 @@ final class EaseeModuleStrukturTest extends TestCase
|
|||||||
self::assertStringContainsString("'Phasenzahl'", $modul);
|
self::assertStringContainsString("'Phasenzahl'", $modul);
|
||||||
self::assertStringNotContainsString('7500', $modul);
|
self::assertStringNotContainsString('7500', $modul);
|
||||||
self::assertStringNotContainsString('Abfrageintervall', $modul);
|
self::assertStringNotContainsString('Abfrageintervall', $modul);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"RegisterVariableInteger('Fahrzeugstatus', 'Fahrzeugstatus', '', 200)",
|
||||||
|
$modul
|
||||||
|
);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"RegisterVariableFloat('Istleistung', 'Istleistung', '', 170)",
|
||||||
|
$modul
|
||||||
|
);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"RegisterVariableInteger('Sollleistung', 'Sollleistung', '', 180)",
|
||||||
|
$modul
|
||||||
|
);
|
||||||
|
self::assertStringContainsString('RegeluebergangTimeout', $modul);
|
||||||
self::assertStringContainsString("'action' => 'StartCharging'", $modul);
|
self::assertStringContainsString("'action' => 'StartCharging'", $modul);
|
||||||
|
|
||||||
$gateway = (string) file_get_contents(
|
$gateway = (string) file_get_contents(
|
||||||
|
|||||||
@@ -9,6 +9,24 @@ use PHPUnit\Framework\TestCase;
|
|||||||
|
|
||||||
final class LadestationReglerTest extends TestCase
|
final class LadestationReglerTest extends TestCase
|
||||||
{
|
{
|
||||||
|
public function testPhasenprobeUnterscheidetBeiMindeststromOhneMaximalstromsprung(): void
|
||||||
|
{
|
||||||
|
self::assertSame(
|
||||||
|
LadestationRegler::PHASEN_EIN,
|
||||||
|
LadestationRegler::erkennePhasenzahlAusLeistung(1380.0, 6)
|
||||||
|
);
|
||||||
|
self::assertSame(
|
||||||
|
LadestationRegler::PHASEN_DREI,
|
||||||
|
LadestationRegler::erkennePhasenzahlAusLeistung(4104.0, 6)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPhasenprobeWeistUngueltigenErkennungsstromAb(): void
|
||||||
|
{
|
||||||
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
LadestationRegler::erkennePhasenzahlAusLeistung(4104.0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
public function testFahrzeugUndDreiPhasenWerdenWieInEnelixEinsErkannt(): void
|
public function testFahrzeugUndDreiPhasenWerdenWieInEnelixEinsErkannt(): void
|
||||||
{
|
{
|
||||||
$status = LadestationRegler::normalisiereStatus([
|
$status = LadestationRegler::normalisiereStatus([
|
||||||
|
|||||||
@@ -88,6 +88,20 @@ final class LadestationStandAloneModulstrukturTest extends TestCase
|
|||||||
self::assertStringContainsString("EnableAction('Solarladen')", $modul);
|
self::assertStringContainsString("EnableAction('Solarladen')", $modul);
|
||||||
self::assertStringContainsString("ReadPropertyBoolean('LoggingEin')", $modul);
|
self::assertStringContainsString("ReadPropertyBoolean('LoggingEin')", $modul);
|
||||||
self::assertStringContainsString("ReadPropertyBoolean('EinstellungenInVisu')", $modul);
|
self::assertStringContainsString("ReadPropertyBoolean('EinstellungenInVisu')", $modul);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"RegisterVariableInteger('Fahrzeugstatus', 'Fahrzeugstatus', '', 200)",
|
||||||
|
$modul
|
||||||
|
);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"RegisterVariableFloat('Istleistung', 'Istleistung', '', 170)",
|
||||||
|
$modul
|
||||||
|
);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"RegisterVariableInteger('Sollleistung', 'Sollleistung', '', 180)",
|
||||||
|
$modul
|
||||||
|
);
|
||||||
|
self::assertStringContainsString('RegeluebergangTimeout', $modul);
|
||||||
|
self::assertStringContainsString('PHASENERKENNUNGSSTROM = 6', $modul);
|
||||||
self::assertStringContainsString('UnregisterVariable($ident)', $modul);
|
self::assertStringContainsString('UnregisterVariable($ident)', $modul);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,58 @@ return static function (TestContext $test): void {
|
|||||||
$test->assertInstanceStatus($station);
|
$test->assertInstanceStatus($station);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$test->runCase('Solarumschaltung wartet auf die neue Manager-Vorgabe', static function (
|
||||||
|
TestContext $test
|
||||||
|
) use ($station): void {
|
||||||
|
$managerId = $test->createInstance(
|
||||||
|
'{6F771B18-59D4-4C8A-B951-3B2FE9F6A2C4}',
|
||||||
|
'Hilfsmanager Easee-Uebergang',
|
||||||
|
[
|
||||||
|
'AutomatischeSuche' => false,
|
||||||
|
'VerbraucherZuordnung' => json_encode([
|
||||||
|
['InstanzID' => $station, 'Aktiv' => true],
|
||||||
|
], JSON_THROW_ON_ERROR),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$sendeSollwert = static function (int $leistung) use ($managerId, $station): void {
|
||||||
|
IPS_RequestAction($station, 'ManagerdatenEmpfangen', json_encode([
|
||||||
|
'Kopf' => [
|
||||||
|
'Version' => '4.0',
|
||||||
|
'AbsenderID' => $managerId,
|
||||||
|
'EmpfaengerID' => $station,
|
||||||
|
'Zeitpunkt' => time(),
|
||||||
|
],
|
||||||
|
'Betriebsart' => 'PV',
|
||||||
|
'Sollleistung_W' => $leistung,
|
||||||
|
], JSON_THROW_ON_ERROR));
|
||||||
|
};
|
||||||
|
|
||||||
|
$sendeSollwert(4104);
|
||||||
|
$befehlVorUmschaltung = (string) GetValue(
|
||||||
|
$test->objectByIdent('LetzterGeraetebefehl', $station)
|
||||||
|
);
|
||||||
|
IPS_RequestAction($station, 'Solarladen', false);
|
||||||
|
|
||||||
|
$test->assertSame(
|
||||||
|
$befehlVorUmschaltung,
|
||||||
|
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $station))
|
||||||
|
);
|
||||||
|
$test->assertSame(
|
||||||
|
4104,
|
||||||
|
GetValue($test->objectByIdent('Sollleistung', $station)),
|
||||||
|
'Die Sollleistung muss bis zur neuen Manager-Vorgabe stabil bleiben.'
|
||||||
|
);
|
||||||
|
|
||||||
|
$sendeSollwert(10944);
|
||||||
|
$test->assertTrue(str_contains(
|
||||||
|
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $station)),
|
||||||
|
'"Ampere":16'
|
||||||
|
));
|
||||||
|
|
||||||
|
IPS_RequestAction($station, 'Solarladen', true);
|
||||||
|
$sendeSollwert(0);
|
||||||
|
});
|
||||||
|
|
||||||
$test->runCase('SignalR-Abbruch erreicht die Ladestation', static function (
|
$test->runCase('SignalR-Abbruch erreicht die Ladestation', static function (
|
||||||
TestContext $test
|
TestContext $test
|
||||||
) use ($gateway, $station): void {
|
) use ($gateway, $station): void {
|
||||||
@@ -226,4 +278,24 @@ return static function (TestContext $test): void {
|
|||||||
);
|
);
|
||||||
$test->assertInstanceStatus($station, 202);
|
$test->assertInstanceStatus($station, 202);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$test->runCase('Leistungswerte und Fahrzeugstatus folgen ihrer Sichtbarkeitsgruppe', static function (
|
||||||
|
TestContext $test
|
||||||
|
) use ($station): void {
|
||||||
|
IPS_SetProperty($station, 'EinstellungenInVisu', true);
|
||||||
|
IPS_SetProperty($station, 'DiagnosevariablenAnzeigen', false);
|
||||||
|
IPS_ApplyChanges($station);
|
||||||
|
|
||||||
|
$test->assertTrue(@IPS_GetObjectIDByIdent('Istleistung', $station) !== false);
|
||||||
|
$test->assertTrue(@IPS_GetObjectIDByIdent('Sollleistung', $station) !== false);
|
||||||
|
$test->assertSame(false, @IPS_GetObjectIDByIdent('Fahrzeugstatus', $station));
|
||||||
|
|
||||||
|
IPS_SetProperty($station, 'EinstellungenInVisu', false);
|
||||||
|
IPS_SetProperty($station, 'DiagnosevariablenAnzeigen', true);
|
||||||
|
IPS_ApplyChanges($station);
|
||||||
|
|
||||||
|
$test->assertSame(false, @IPS_GetObjectIDByIdent('Istleistung', $station));
|
||||||
|
$test->assertSame(false, @IPS_GetObjectIDByIdent('Sollleistung', $station));
|
||||||
|
$test->assertTrue(@IPS_GetObjectIDByIdent('Fahrzeugstatus', $station) !== false);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -361,7 +361,18 @@ return static function (TestContext $test): void {
|
|||||||
'amp=6'
|
'amp=6'
|
||||||
), 'Solarladen: Der 6-A-Befehl fehlt. Erhalten: ' . $befehl . '; Diagnose: ' . $diagnose);
|
), 'Solarladen: Der 6-A-Befehl fehlt. Erhalten: ' . $befehl . '; Diagnose: ' . $diagnose);
|
||||||
|
|
||||||
|
$befehlVorUmschaltung = $befehl;
|
||||||
IPS_RequestAction($stationId, 'Solarladen', false);
|
IPS_RequestAction($stationId, 'Solarladen', false);
|
||||||
|
$test->assertSame(
|
||||||
|
$befehlVorUmschaltung,
|
||||||
|
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)),
|
||||||
|
'Die Umschaltung darf vor der neuen Manager-Vorgabe keinen Zwischenwert setzen.'
|
||||||
|
);
|
||||||
|
$test->assertSame(
|
||||||
|
4104,
|
||||||
|
GetValue($test->objectByIdent('Sollleistung', $stationId)),
|
||||||
|
'Die Sollleistung muss bis zur neuen Manager-Vorgabe stabil bleiben.'
|
||||||
|
);
|
||||||
$angebot = (string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId));
|
$angebot = (string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId));
|
||||||
$test->assertSame('[10944]', $angebot, 'PV ohne Solarladen muss nur das Maximum anbieten.');
|
$test->assertSame('[10944]', $angebot, 'PV ohne Solarladen muss nur das Maximum anbieten.');
|
||||||
$abgewiesen = false;
|
$abgewiesen = false;
|
||||||
@@ -422,7 +433,7 @@ return static function (TestContext $test): void {
|
|||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
$test->runCase('Neue Ladestation wird erst nach Freigabe mit Maximalstrom erkannt', static function (
|
$test->runCase('Neue Ladestation wird erst nach Freigabe mit Mindeststrom erkannt', static function (
|
||||||
TestContext $test
|
TestContext $test
|
||||||
) use ($phasenerkennung, $anforderungSenden): void {
|
) use ($phasenerkennung, $anforderungSenden): void {
|
||||||
$stationId = $phasenerkennung;
|
$stationId = $phasenerkennung;
|
||||||
@@ -432,8 +443,8 @@ return static function (TestContext $test): void {
|
|||||||
);
|
);
|
||||||
$test->assertTrue(!str_contains(
|
$test->assertTrue(!str_contains(
|
||||||
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)),
|
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)),
|
||||||
'amp=16'
|
'amp=6'
|
||||||
), 'Eine inaktive Station darf keine Maximalstrom-Probe starten.');
|
), 'Eine inaktive Station darf keine Phasenprobe starten.');
|
||||||
|
|
||||||
IPS_RequestAction($stationId, 'Aktiv', true);
|
IPS_RequestAction($stationId, 'Aktiv', true);
|
||||||
|
|
||||||
@@ -443,8 +454,8 @@ return static function (TestContext $test): void {
|
|||||||
);
|
);
|
||||||
$test->assertTrue(str_contains(
|
$test->assertTrue(str_contains(
|
||||||
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)),
|
(string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)),
|
||||||
'amp=16'
|
'amp=6'
|
||||||
), 'Nach der Freigabe muss die Maximalstrom-Probe starten.');
|
), 'Nach der Freigabe muss die Mindeststrom-Phasenprobe starten.');
|
||||||
|
|
||||||
IPS_Sleep(2100);
|
IPS_Sleep(2100);
|
||||||
IPS_RequestAction($stationId, 'Statuszyklus', false);
|
IPS_RequestAction($stationId, 'Statuszyklus', false);
|
||||||
@@ -472,4 +483,25 @@ return static function (TestContext $test): void {
|
|||||||
(string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId))
|
(string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$test->runCase('Leistungswerte und Fahrzeugstatus folgen ihrer Sichtbarkeitsgruppe', static function (
|
||||||
|
TestContext $test
|
||||||
|
) use ($stationen): void {
|
||||||
|
$stationId = $stationen['go-e alt'];
|
||||||
|
IPS_SetProperty($stationId, 'EinstellungenInVisu', true);
|
||||||
|
IPS_SetProperty($stationId, 'DiagnosevariablenAnzeigen', false);
|
||||||
|
IPS_ApplyChanges($stationId);
|
||||||
|
|
||||||
|
$test->assertTrue(@IPS_GetObjectIDByIdent('Istleistung', $stationId) !== false);
|
||||||
|
$test->assertTrue(@IPS_GetObjectIDByIdent('Sollleistung', $stationId) !== false);
|
||||||
|
$test->assertSame(false, @IPS_GetObjectIDByIdent('Fahrzeugstatus', $stationId));
|
||||||
|
|
||||||
|
IPS_SetProperty($stationId, 'EinstellungenInVisu', false);
|
||||||
|
IPS_SetProperty($stationId, 'DiagnosevariablenAnzeigen', true);
|
||||||
|
IPS_ApplyChanges($stationId);
|
||||||
|
|
||||||
|
$test->assertSame(false, @IPS_GetObjectIDByIdent('Istleistung', $stationId));
|
||||||
|
$test->assertSame(false, @IPS_GetObjectIDByIdent('Sollleistung', $stationId));
|
||||||
|
$test->assertTrue(@IPS_GetObjectIDByIdent('Fahrzeugstatus', $stationId) !== false);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user