This commit is contained in:
@@ -4,6 +4,12 @@ Alle wesentlichen Aenderungen an Enelix EMS werden in dieser Datei dokumentiert.
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Manager: Energy Pie verwendet die bilanzielle Gesamtanlage inklusive SDL
|
||||||
|
unabhaengig von SDLAktiv. Kein Mischen des SDL-bereinigten Hauszaehlers mit
|
||||||
|
physischen Netzzaehlern, keine doppelte Addition von SDL-Energie. Benoetigt
|
||||||
|
zuerst Enelix Utils mit Gesamtbilanz-Unterstuetzung; Quellen, Farben, Archive,
|
||||||
|
Hauslast fuer Regelung/Prognose und Stellpfade bleiben unveraendert.
|
||||||
|
|
||||||
- Ladestation Stand-Alone: Ladepausen und einzelne Nullwerte verriegeln das
|
- Ladestation Stand-Alone: Ladepausen und einzelne Nullwerte verriegeln das
|
||||||
Fahrzeug nicht mehr als geladen. Ladeende nur mit aktuellem eindeutigen
|
Fahrzeug nicht mehr als geladen. Ladeende nur mit aktuellem eindeutigen
|
||||||
Geraetesignal; Pico hat kein solches Voll-Signal. go-e-Fehler, Pico-Status
|
Geraetesignal; Pico hat kein solches Voll-Signal. go-e-Fehler, Pico-Status
|
||||||
|
|||||||
@@ -405,6 +405,30 @@ der wirksamen Lastspitzengrenze zu `Peak`. Zwischen den beiden Zielwerten
|
|||||||
bleibt sie erhalten. `Umschaltdifferenz` verhindert zusätzlich einen Wechsel,
|
bleibt sie erhalten. `Umschaltdifferenz` verhindert zusätzlich einen Wechsel,
|
||||||
wenn sich die beiden berechneten Korrekturen nicht ausreichend unterscheiden.
|
wenn sich die beiden berechneten Korrekturen nicht ausreichend unterscheiden.
|
||||||
|
|
||||||
|
## Energy Pie: Gesamtbilanz inklusive SDL
|
||||||
|
|
||||||
|
Der Manager aktiviert am eigenen Energy Pie `Gesamtbilanz=true`, unabhaengig
|
||||||
|
von `SDLAktiv`. Der bilanzielle Gesamtverbrauch ist Produktion plus physischer
|
||||||
|
Netzbezug minus Einspeisung (mindestens 0). SDL-Ladung bzw. -Abgabe wirkt damit
|
||||||
|
ueber die bereits vorhandenen Netzzaehler; separate SDL-Zaehler werden nicht
|
||||||
|
nochmals addiert. Eine Versorgung des Hauses durch SDL ist keine Netzeinspeisung.
|
||||||
|
Die Hausquelle bleibt gespeichert, fliesst jedoch nicht in diese Gesamtbilanz ein.
|
||||||
|
Die weiterhin SDL-bereinigte Hauslast fuer Regelung und Prognose bleibt unveraendert.
|
||||||
|
|
||||||
|
Die Quoten sind ausdruecklich **bilanziell**, keine reine PV-Herkunftszuordnung
|
||||||
|
oder physische Hausautarkie. Speicherentladung kann den Netto-Bilanzverbrauch
|
||||||
|
senken; bei negativem Saldo zeigt der Pie einen Hinweis und begrenzt Verbrauch
|
||||||
|
und Quoten auf 0. Fehlende Daten werden weiterhin als unbekannt behandelt.
|
||||||
|
|
||||||
|
Migration: zuerst Enelix Utils mit Gesamtbilanz-Unterstuetzung aktualisieren,
|
||||||
|
dann den EMS-Manager anwenden. Zaehlervariablen, Archivdaten und individuelle
|
||||||
|
Farben bleiben erhalten. Historische Zeitraeume werden neu aus den vorhandenen
|
||||||
|
drei Zaehlern berechnet. Die alte Property `EnergieanteileBerechenbar` bleibt
|
||||||
|
fuer einen Rueckwechsel erhalten und blockiert die Gesamtbilanz nicht.
|
||||||
|
Mit einem alten Utils bleibt die bisherige SDL-Schutzlogik bestehen, bis Utils
|
||||||
|
aktualisiert wird; es wird keine falsche Hausbilanz erzwungen. Kein Anlagenrollout
|
||||||
|
oder Stellbefehl ist Teil dieser Quellcode-Aenderung.
|
||||||
|
|
||||||
## Laufzeit und Fehlerverhalten
|
## Laufzeit und Fehlerverhalten
|
||||||
|
|
||||||
- Netzleistungsänderungen und Verbrauchermeldungen lösen die Berechnung aus.
|
- Netzleistungsänderungen und Verbrauchermeldungen lösen die Berechnung aus.
|
||||||
|
|||||||
@@ -297,9 +297,21 @@ trait ManagerEnergieTrait
|
|||||||
|
|
||||||
private function synchronisiereEnergyPieAnteile(int $instanzID, bool $anwenden = true): void
|
private function synchronisiereEnergyPieAnteile(int $instanzID, bool $anwenden = true): void
|
||||||
{
|
{
|
||||||
// Physischer Netzbezug enthaelt SDL, die Hausenergie dagegen nicht.
|
|
||||||
$berechenbar = !$this->ReadPropertyBoolean('SDLAktiv');
|
|
||||||
$konfiguration = json_decode(IPS_GetConfiguration($instanzID), true, 512, JSON_THROW_ON_ERROR);
|
$konfiguration = json_decode(IPS_GetConfiguration($instanzID), true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
if (is_array($konfiguration) && array_key_exists('Gesamtbilanz', $konfiguration)) {
|
||||||
|
// Physical grid counters already include SDL; Utils derives the complete site balance.
|
||||||
|
IPS_SetHidden($instanzID, false);
|
||||||
|
if (IPS_GetProperty($instanzID, 'Gesamtbilanz') !== true) {
|
||||||
|
IPS_SetProperty($instanzID, 'Gesamtbilanz', true);
|
||||||
|
if ($anwenden) {
|
||||||
|
IPS_ApplyChanges($instanzID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compatibility until Utils is updated: do not enable the old mixed-boundary calculation.
|
||||||
|
$berechenbar = !$this->ReadPropertyBoolean('SDLAktiv');
|
||||||
if (!is_array($konfiguration) || !array_key_exists('EnergieanteileBerechenbar', $konfiguration)) {
|
if (!is_array($konfiguration) || !array_key_exists('EnergieanteileBerechenbar', $konfiguration)) {
|
||||||
IPS_SetHidden($instanzID, !$berechenbar);
|
IPS_SetHidden($instanzID, !$berechenbar);
|
||||||
if (!$berechenbar) {
|
if (!$berechenbar) {
|
||||||
|
|||||||
@@ -413,6 +413,44 @@ final class ManagerSDLTest extends TestCase
|
|||||||
self::assertSame($custom, ManagerSDLRuntime::$properties[303]);
|
self::assertSame($custom, ManagerSDLRuntime::$properties[303]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testModernEnergyPieUsesOverallBalanceWithAndWithoutSDL(): void
|
||||||
|
{
|
||||||
|
$custom = [
|
||||||
|
'ProduktionZaehlerID' => 801, 'NetzbezugZaehlerID' => 802,
|
||||||
|
'EinspeisungZaehlerID' => 803, 'VerbrauchZaehlerID' => 804,
|
||||||
|
'FarbeEigenverbrauch' => '#123456', 'FarbeAutarkie' => '#ABCDEF',
|
||||||
|
'Standardzeitraum' => 'month', 'EnergieanteileBerechenbar' => false,
|
||||||
|
'Gesamtbilanz' => false,
|
||||||
|
];
|
||||||
|
foreach ([true, false] as $sdl) {
|
||||||
|
ManagerSDLRuntime::$properties[303] = $custom;
|
||||||
|
ManagerSDLRuntime::$hidden[303] = true;
|
||||||
|
$this->properties(['SDLAktiv' => $sdl]);
|
||||||
|
$this->invoke('synchronisiereEnergyPieAnteile', [303]);
|
||||||
|
self::assertSame(array_replace($custom, ['Gesamtbilanz' => true]),
|
||||||
|
ManagerSDLRuntime::$properties[303]);
|
||||||
|
self::assertFalse(ManagerSDLRuntime::$hidden[303]);
|
||||||
|
$writes = ManagerSDLRuntime::$writes;
|
||||||
|
$this->invoke('synchronisiereEnergyPieAnteile', [303]);
|
||||||
|
self::assertSame($writes, ManagerSDLRuntime::$writes);
|
||||||
|
}
|
||||||
|
self::assertSame([], ManagerSDLRuntime::$logs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUtilsUpgradeRestoresBalanceWithoutResettingCustomSources(): void
|
||||||
|
{
|
||||||
|
ManagerSDLRuntime::$properties[303] = ['ProduktionZaehlerID' => 801];
|
||||||
|
$this->properties(['SDLAktiv' => true]);
|
||||||
|
$this->invoke('synchronisiereEnergyPieAnteile', [303]);
|
||||||
|
self::assertTrue(ManagerSDLRuntime::$hidden[303]);
|
||||||
|
ManagerSDLRuntime::$properties[303]['Gesamtbilanz'] = false;
|
||||||
|
ManagerSDLRuntime::$properties[303]['EnergieanteileBerechenbar'] = false;
|
||||||
|
$this->invoke('synchronisiereEnergyPieAnteile', [303]);
|
||||||
|
self::assertFalse(ManagerSDLRuntime::$hidden[303]);
|
||||||
|
self::assertTrue(ManagerSDLRuntime::$properties[303]['Gesamtbilanz']);
|
||||||
|
self::assertSame(801, ManagerSDLRuntime::$properties[303]['ProduktionZaehlerID']);
|
||||||
|
}
|
||||||
|
|
||||||
public function testOlderEnergyPieStaysVisibleWithoutSDLAndKeepsConfiguration(): void
|
public function testOlderEnergyPieStaysVisibleWithoutSDLAndKeepsConfiguration(): void
|
||||||
{
|
{
|
||||||
$custom = ['ProduktionZaehlerID' => 801, 'FarbeEigenverbrauch' => '#123456'];
|
$custom = ['ProduktionZaehlerID' => 801, 'FarbeEigenverbrauch' => '#123456'];
|
||||||
|
|||||||
Reference in New Issue
Block a user