This commit is contained in:
+7
-2
@@ -156,7 +156,12 @@ class Manager extends IPSModule implements ManagerSchnittstelle
|
|||||||
$this->SetTimerInterval('KeepAlive', $this->ReadPropertyInteger('KeepAlive') * 1000);
|
$this->SetTimerInterval('KeepAlive', $this->ReadPropertyInteger('KeepAlive') * 1000);
|
||||||
$this->setzeDiagnosewert('Monatsgrenzen', $this->ReadPropertyString('Monatsgrenzen'));
|
$this->setzeDiagnosewert('Monatsgrenzen', $this->ReadPropertyString('Monatsgrenzen'));
|
||||||
$this->aktualisiereAnschlussstatus();
|
$this->aktualisiereAnschlussstatus();
|
||||||
if (!$this->aktualisiereLizenzfreigabe($this->ReadPropertyString('Lizenzcode'), false)) {
|
$geraetezugangFehlt = $this->hatAnlagentopologie()
|
||||||
|
&& $this->ReadAttributeString('PrognoseInstallationsToken') === '';
|
||||||
|
if (!$this->aktualisiereLizenzfreigabe(
|
||||||
|
$this->ReadPropertyString('Lizenzcode'),
|
||||||
|
$geraetezugangFehlt
|
||||||
|
)) {
|
||||||
$this->SetValue('Betriebsart', ManagerRegler::BETRIEBSART_INAKTIV);
|
$this->SetValue('Betriebsart', ManagerRegler::BETRIEBSART_INAKTIV);
|
||||||
$this->SetStatus(self::STATUS_LIZENZ_UNGUELTIG);
|
$this->SetStatus(self::STATUS_LIZENZ_UNGUELTIG);
|
||||||
return;
|
return;
|
||||||
@@ -265,7 +270,7 @@ class Manager extends IPSModule implements ManagerSchnittstelle
|
|||||||
{
|
{
|
||||||
return json_encode(
|
return json_encode(
|
||||||
$this->leseAnlagentopologie(),
|
$this->leseAnlagentopologie(),
|
||||||
JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES
|
JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ Die Demo erzeugt idempotent eine vollständige, spielbare EMS-Anlage in IP-Symco
|
|||||||
- einen einstufigen Entfeuchter (0,9 kW),
|
- einen einstufigen Entfeuchter (0,9 kW),
|
||||||
- einen zweistufigen Pufferspeicher (1,8/3,6 kW) mit Heizkurve,
|
- einen zweistufigen Pufferspeicher (1,8/3,6 kW) mit Heizkurve,
|
||||||
- einen bidirektionalen Batteriespeicher (10 kWh, +/-3,5 kW),
|
- einen bidirektionalen Batteriespeicher (10 kWh, +/-3,5 kW),
|
||||||
|
- eine technische Anlagentopologie mit Hybridwechselrichter, PV-Fläche und
|
||||||
|
Batteriespeicher für die Prognoseanbindung,
|
||||||
- simulierte PV-Erzeugung, variable Bewölkung, Tageslastgang, Zusatzlast,
|
- simulierte PV-Erzeugung, variable Bewölkung, Tageslastgang, Zusatzlast,
|
||||||
Außentemperatur, Wärmeverluste, Netzleistung und Speicherzustände,
|
Außentemperatur, Wärmeverluste, Netzleistung und Speicherzustände,
|
||||||
- native Symcon-Instanz `Energy Distribution` für acht Energieflussknoten,
|
- native Symcon-Instanz `Energy Distribution` für acht Energieflussknoten,
|
||||||
@@ -39,6 +41,12 @@ damit keine Lizenzfehler protokolliert werden. Nach der Aktivierung den
|
|||||||
Bootstrap erneut ausführen; er ordnet dann alle fünf Teilnehmer zu und startet
|
Bootstrap erneut ausführen; er ordnet dann alle fünf Teilnehmer zu und startet
|
||||||
die Regelung.
|
die Regelung.
|
||||||
|
|
||||||
|
Die Demo übernimmt die einstellbare PV-Spitzenleistung als AC- und
|
||||||
|
DC-Anlagenleistung. Für die feste Beispieltopologie gelten 30 Grad Neigung und
|
||||||
|
Südausrichtung. Der 10-kWh-Speicher nutzt den gemeinsamen Hybridwechselrichter;
|
||||||
|
seine dynamischen Lade- und Entladegrenzen werden beim Bootstrap in die
|
||||||
|
technischen Stammdaten übernommen.
|
||||||
|
|
||||||
## Bedienung
|
## Bedienung
|
||||||
|
|
||||||
In der Kachelvisualisierung öffnet die Startkategorie `Enelix 2 Demoanlage`.
|
In der Kachelvisualisierung öffnet die Startkategorie `Enelix 2 Demoanlage`.
|
||||||
|
|||||||
@@ -277,6 +277,39 @@ function enelixDemoInstall(): array
|
|||||||
static fn (int $id): array => ['InstanzID' => $id, 'Aktiv' => true],
|
static fn (int $id): array => ['InstanzID' => $id, 'Aktiv' => true],
|
||||||
[$boiler1, $boiler2, $dryer, $buffer, $battery]
|
[$boiler1, $boiler2, $dryer, $buffer, $battery]
|
||||||
);
|
);
|
||||||
|
$pvNennleistungKw = max(0.1, (float) GetValue($peak) / 1000.0);
|
||||||
|
$wechselrichterKonfiguration = [[
|
||||||
|
'ID' => 'demo-hybrid-1',
|
||||||
|
'Name' => 'Demo-Hybridwechselrichter',
|
||||||
|
'Typ' => 'hybrid',
|
||||||
|
'ACNennleistung_kW' => $pvNennleistungKw,
|
||||||
|
'ACEinspeisegrenze_kW' => 0.0,
|
||||||
|
'ACBezugsgrenze_kW' => 0.0,
|
||||||
|
]];
|
||||||
|
$pvKonfiguration = [[
|
||||||
|
'ID' => 'demo-pv-1',
|
||||||
|
'Name' => 'Demo-PV-Anlage',
|
||||||
|
'DCLeistung_kWp' => $pvNennleistungKw,
|
||||||
|
'Neigung_Grad' => 30.0,
|
||||||
|
'Azimut_Grad' => 0.0,
|
||||||
|
'WechselrichterID' => 'demo-hybrid-1',
|
||||||
|
'MPPT' => 'A',
|
||||||
|
'Modulanzahl' => 0,
|
||||||
|
'Modulleistung_Wp' => 0.0,
|
||||||
|
]];
|
||||||
|
$batterieKonfiguration = [[
|
||||||
|
'ID' => 'demo-battery-1',
|
||||||
|
'Name' => 'Batteriespeicher 10 kWh',
|
||||||
|
'Nennkapazitaet_kWh' => 10.0,
|
||||||
|
'Nutzkapazitaet_kWh' => 10.0,
|
||||||
|
'MaxLadeleistung_kW' => max(0.1, (float) GetValue($batteryMaxCharge) / 1000.0),
|
||||||
|
'MaxEntladeleistung_kW' => max(
|
||||||
|
0.1,
|
||||||
|
(float) GetValue($batteryMaxDischarge) / 1000.0
|
||||||
|
),
|
||||||
|
'WechselrichterID' => 'demo-hybrid-1',
|
||||||
|
'Kopplung' => 'hybrid',
|
||||||
|
]];
|
||||||
$managerProperties = [
|
$managerProperties = [
|
||||||
'NetzleistungVariableID' => $grid,
|
'NetzleistungVariableID' => $grid,
|
||||||
'Netzleistungsfaktor' => 1.0,
|
'Netzleistungsfaktor' => 1.0,
|
||||||
@@ -288,6 +321,15 @@ function enelixDemoInstall(): array
|
|||||||
'VerbraucherTimeout' => 15,
|
'VerbraucherTimeout' => 15,
|
||||||
'SollwertSolarladen' => 0.0,
|
'SollwertSolarladen' => 0.0,
|
||||||
'Umschaltdifferenz' => 0.0,
|
'Umschaltdifferenz' => 0.0,
|
||||||
|
'AnlagenWechselrichter' => json_encode(
|
||||||
|
$wechselrichterKonfiguration,
|
||||||
|
JSON_THROW_ON_ERROR
|
||||||
|
),
|
||||||
|
'AnlagenPVFlaechen' => json_encode($pvKonfiguration, JSON_THROW_ON_ERROR),
|
||||||
|
'AnlagenBatterien' => json_encode(
|
||||||
|
$batterieKonfiguration,
|
||||||
|
JSON_THROW_ON_ERROR
|
||||||
|
),
|
||||||
'DiagnosevariablenAnzeigen' => true,
|
'DiagnosevariablenAnzeigen' => true,
|
||||||
'LoggingEin' => false,
|
'LoggingEin' => false,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -116,6 +116,12 @@ final class DemoanlageBootstrapTest extends TestCase
|
|||||||
self::assertStringContainsString("'BatterieListe'", $source);
|
self::assertStringContainsString("'BatterieListe'", $source);
|
||||||
self::assertStringContainsString('ENELIX_DEMO_BUFFER_MODULE', $source);
|
self::assertStringContainsString('ENELIX_DEMO_BUFFER_MODULE', $source);
|
||||||
self::assertStringContainsString('ENELIX_DEMO_BATTERY_MODULE', $source);
|
self::assertStringContainsString('ENELIX_DEMO_BATTERY_MODULE', $source);
|
||||||
|
self::assertStringContainsString("'AnlagenWechselrichter'", $source);
|
||||||
|
self::assertStringContainsString("'AnlagenPVFlaechen'", $source);
|
||||||
|
self::assertStringContainsString("'AnlagenBatterien'", $source);
|
||||||
|
self::assertStringContainsString("'demo-hybrid-1'", $source);
|
||||||
|
self::assertStringContainsString("'demo-pv-1'", $source);
|
||||||
|
self::assertStringContainsString("'demo-battery-1'", $source);
|
||||||
self::assertStringContainsString("'EnergieflussPVkW'", $source);
|
self::assertStringContainsString("'EnergieflussPVkW'", $source);
|
||||||
self::assertStringContainsString("'~Power'", $source);
|
self::assertStringContainsString("'~Power'", $source);
|
||||||
self::assertStringContainsString("'~Electricity'", $source);
|
self::assertStringContainsString("'~Electricity'", $source);
|
||||||
|
|||||||
@@ -186,8 +186,17 @@ final class ManagerModulstrukturTest extends TestCase
|
|||||||
"RegisterAttributeString('PrognoseInstallationsToken', '')",
|
"RegisterAttributeString('PrognoseInstallationsToken', '')",
|
||||||
$inhalt
|
$inhalt
|
||||||
);
|
);
|
||||||
|
self::assertStringContainsString('JSON_PRESERVE_ZERO_FRACTION', $inhalt);
|
||||||
self::assertStringContainsString("'issueDeviceToken' =>", $inhalt);
|
self::assertStringContainsString("'issueDeviceToken' =>", $inhalt);
|
||||||
self::assertStringContainsString("unset(\$neueLease['deviceToken'])", $inhalt);
|
self::assertStringContainsString("unset(\$neueLease['deviceToken'])", $inhalt);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"\$geraetezugangFehlt = \$this->hatAnlagentopologie()",
|
||||||
|
$inhalt
|
||||||
|
);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"\$this->ReadPropertyString('Lizenzcode'),\n \$geraetezugangFehlt",
|
||||||
|
$inhalt
|
||||||
|
);
|
||||||
self::assertStringContainsString('synchronisiereAnlagentopologie()', $inhalt);
|
self::assertStringContainsString('synchronisiereAnlagentopologie()', $inhalt);
|
||||||
self::assertStringContainsString("'Authorization: Bearer ' . \$token", $inhalt);
|
self::assertStringContainsString("'Authorization: Bearer ' . \$token", $inhalt);
|
||||||
self::assertStringNotContainsString(
|
self::assertStringNotContainsString(
|
||||||
|
|||||||
Reference in New Issue
Block a user