feat(manager): Energievisualisierung und Synchronisierung erweitern
Tests / test (push) Successful in 50s

This commit is contained in:
dh
2026-10-06 08:00:30 +00:00
parent 8d83b083bf
commit 37addf4242
5 changed files with 864 additions and 111 deletions
+63 -11
View File
@@ -171,6 +171,10 @@ class Manager extends IPSModule implements ManagerSchnittstelle
$this->RegisterPropertyInteger('EnergieLoeschenMonate', 0);
$this->RegisterPropertyBoolean('EnergyPieAnzeigen', false);
$this->RegisterPropertyBoolean('EnergiediagrammeAnzeigen', false);
$this->RegisterPropertyInteger('DiagrammPVModus', 0);
$this->RegisterPropertyInteger('DiagrammBatterieModus', 0);
$this->RegisterPropertyBoolean('LadestationenSeparatAnzeigen', true);
$this->RegisterPropertyBoolean('VerbraucherSeparatAnzeigen', true);
$this->RegisterPropertyBoolean('FunFactsAnzeigen', false);
$this->RegisterPropertyBoolean('EnergieflussAnzeigen', false);
$this->RegisterPropertyInteger('EnergieflussLeistungseinheit', 0);
@@ -203,6 +207,9 @@ class Manager extends IPSModule implements ManagerSchnittstelle
$this->RegisterAttributeInteger('MessungLetzteEnergieaufzeichnung', 0);
$this->RegisterAttributeString('MessungEnergiePuffer', '{}');
$this->RegisterAttributeString('MessungZaehlerstaende', '{}');
$this->RegisterAttributeString('EnergiediagrammKonfiguration', '{}');
$this->RegisterAttributeString('EnergieflussKonfiguration', '{}');
$this->RegisterAttributeBoolean('EnergieflussNeuErzeugen', false);
// Die alten Timer bleiben deaktiviert registriert, damit bestehende Instanzen sauber migrieren.
$this->RegisterTimer('Regelzyklus', 0, '');
@@ -238,8 +245,8 @@ class Manager extends IPSModule implements ManagerSchnittstelle
try {
$this->pruefeKonfiguration();
$this->konfiguriereEnergiearchiv();
$this->synchronisiereEnergievisualisierungen();
$this->konfiguriereEnergiearchiv();
} catch (Throwable $fehler) {
$this->SetStatus(self::STATUS_KONFIGURATION_UNGUELTIG);
$this->SetTimerInterval('Regelzyklus', 0);
@@ -616,7 +623,10 @@ class Manager extends IPSModule implements ManagerSchnittstelle
];
$this->WriteAttributeString('VerbraucherCache', json_encode($cache, JSON_THROW_ON_ERROR));
$this->aktualisiereEnergieflusswerte();
$this->regeln(false);
$this->aktualisiereDiagrammMesswerte();
if ($this->GetBuffer('VerbraucherSynchronisierungAktiv') !== '1') {
$this->regeln(false);
}
}
/** @param array<string, mixed> $daten */
@@ -1008,13 +1018,20 @@ class Manager extends IPSModule implements ManagerSchnittstelle
foreach ($ids as $instanzID) {
$eintrag = $cache[(string) $instanzID] ?? null;
$grund = '';
if (!is_array($eintrag) || !isset($eintrag['EmpfangenAm'], $eintrag['Daten'])) {
$grund = 'Noch keine Meldung';
} elseif (time() - (int) $eintrag['EmpfangenAm'] > $timeout) {
$grund = 'Meldung ist veraltet';
} elseif (($eintrag['Daten']['Betriebsart'] ?? null) !== $betriebsart) {
$grund = 'Leistungsangebot gehoert nicht zur Betriebsart ' . $betriebsart;
$grund = $this->verbraucherMeldegrund($eintrag, $betriebsart, $timeout);
$synchronisierungsfehler = '';
if (in_array($grund, ['Noch keine Meldung', 'Meldung ist veraltet'], true)) {
try {
$this->SetBuffer('VerbraucherSynchronisierungAktiv', '1');
IPS_RequestAction($instanzID, 'Melden', true);
} catch (Throwable $fehler) {
$synchronisierungsfehler = $fehler->getMessage();
} finally {
$this->SetBuffer('VerbraucherSynchronisierungAktiv', '0');
}
$cache = $this->leseJsonAttribut('VerbraucherCache');
$eintrag = $cache[(string) $instanzID] ?? null;
$grund = $this->verbraucherMeldegrund($eintrag, $betriebsart, $timeout);
}
if ($grund !== '') {
@@ -1025,8 +1042,11 @@ class Manager extends IPSModule implements ManagerSchnittstelle
try {
$this->sendeManagerdaten($instanzID, $betriebsart, null);
} catch (Throwable $fehler) {
$stoerungen[] = $detail['Name'] . ': Betriebsart konnte nicht uebermittelt werden: '
. $fehler->getMessage();
$synchronisierungsfehler = $fehler->getMessage();
}
if ($synchronisierungsfehler !== '') {
$stoerungen[] = $detail['Name'] . ': Vollmeldung konnte nicht angefordert werden: '
. $synchronisierungsfehler;
}
continue;
}
@@ -1039,6 +1059,27 @@ class Manager extends IPSModule implements ManagerSchnittstelle
return $aktuell;
}
/** @param array<string, mixed>|null $eintrag */
private function verbraucherMeldegrund(
?array $eintrag,
string $betriebsart,
int $timeout
): string {
if (!isset($eintrag['EmpfangenAm'], $eintrag['Daten'])
|| !is_array($eintrag['Daten'])
) {
return 'Noch keine Meldung';
}
if (time() - (int) $eintrag['EmpfangenAm'] > $timeout) {
return 'Meldung ist veraltet';
}
if (($eintrag['Daten']['Betriebsart'] ?? null) !== $betriebsart) {
return 'Leistungsangebot gehoert nicht zur Betriebsart ' . $betriebsart;
}
return '';
}
private function setzeNichtGeregelteVerbraucher(string $grund): void
{
try {
@@ -2120,6 +2161,7 @@ class Manager extends IPSModule implements ManagerSchnittstelle
$this->WriteAttributeInteger('MessungLetzteEnergieaufzeichnung', $jetzt);
}
$this->aktualisiereDiagrammMesswerte(true);
$funFactsID = @IPS_GetObjectIDByIdent('EnergieFunFacts', $this->InstanceID);
if (is_int($funFactsID) && $funFactsID > 0 && IPS_VariableExists($funFactsID)) {
$this->aktualisiereFunFacts($funFactsID);
@@ -2647,6 +2689,16 @@ class Manager extends IPSModule implements ManagerSchnittstelle
throw new InvalidArgumentException($property . ' darf nicht negativ sein.');
}
}
foreach (['DiagrammPVModus', 'DiagrammBatterieModus'] as $property) {
if (!in_array($this->ReadPropertyInteger($property), [0, 1, 2], true)) {
throw new InvalidArgumentException($property . ' muss 0, 1 oder 2 sein.');
}
}
if (!in_array($this->ReadPropertyInteger('EnergieflussLeistungseinheit'), [0, 1], true)) {
throw new InvalidArgumentException(
'EnergieflussLeistungseinheit muss 0 oder 1 sein.'
);
}
$energieLoeschen = $this->ReadPropertyInteger('EnergieLoeschenMonate');
$energieVerdichten = $this->ReadPropertyInteger('EnergieVerdichtenMonate');
if ($energieLoeschen > 0 && $energieLoeschen <= $energieVerdichten) {