ReadPropertyBoolean('SDLAktiv')) { return; } $leistungID = $this->ReadPropertyInteger('SDLLeistungVariableID'); if (!$this->istNumerischeVariable($leistungID)) { throw new InvalidArgumentException('SDL benoetigt eine numerische Istleistungsvariable.'); } $this->anlagenMessfaktor($this->ReadPropertyFloat('SDLLeistungsfaktor'), 'SDL'); $socID = $this->ReadPropertyInteger('SDLSOCVariableID'); if ($socID !== 0 && (!$this->istNumerischeVariable($socID) || $socID === $leistungID)) { throw new InvalidArgumentException('SDL-SOC muss eine separate numerische Variable sein.'); } $andereQuellen = array_merge($this->pvMessquellen(), $this->batterieMessquellen()); $andereQuellen[] = ['VariableID' => $this->ReadPropertyInteger('NetzleistungVariableID')]; foreach ($andereQuellen as $quelle) { if ($leistungID === $quelle['VariableID']) { throw new InvalidArgumentException( 'SDL-Leistung darf nicht zugleich als PV-, Netz- oder Batterieleistung bilanziert werden.' ); } } } private function synchronisiereSDLMesskonfiguration(): void { $neu = json_encode([ $this->ReadPropertyBoolean('SDLAktiv'), $this->ReadPropertyInteger('SDLLeistungVariableID'), $this->ReadPropertyFloat('SDLLeistungsfaktor'), ], JSON_THROW_ON_ERROR); $alt = $this->ReadAttributeString('SDLMesskonfiguration'); if ($neu !== $alt && ($alt !== '' || $this->ReadPropertyBoolean('SDLAktiv'))) { // Bereits erfasste Energien bleiben erhalten; keine Rueckrechnung mit neuen Quellen. $this->WriteAttributeInteger('MessungLetzterZeitstempel', 0); $this->WriteAttributeString('MessungZaehlerstaende', '{}'); $this->WriteAttributeInteger('MessungLetzteLeistungsaufzeichnung', 0); } $this->WriteAttributeString('SDLMesskonfiguration', $neu); } private function aktuelleSDLLeistung(): float { if (!$this->ReadPropertyBoolean('SDLAktiv')) { return 0.0; } $variableID = $this->ReadPropertyInteger('SDLLeistungVariableID'); if (!$this->istNumerischeVariable($variableID)) { throw new RuntimeException('Die SDL-Istleistung ist nicht verfuegbar.'); } $wert = GetValue($variableID); if ((!is_int($wert) && !is_float($wert)) || !is_finite((float) $wert)) { throw new RuntimeException('Die SDL-Istleistung ist keine endliche Zahl.'); } $leistung = (float) $wert * $this->ReadPropertyFloat('SDLLeistungsfaktor'); if (!is_finite($leistung)) { throw new RuntimeException('Die skalierte SDL-Istleistung ist nicht endlich.'); } if ($this->ReadPropertyInteger('SDLSOCVariableID') === 0 || $this->aktuelleSDLSOC() !== null) { $this->setzeDiagnosewert('SDLStatus', 'Aktiv'); } return $leistung; } private function aktuelleSDLSOC(): ?float { if (!$this->ReadPropertyBoolean('SDLAktiv')) { return null; } $variableID = $this->ReadPropertyInteger('SDLSOCVariableID'); if ($variableID === 0) { return null; } if ($this->istNumerischeVariable($variableID)) { $wert = (float) GetValue($variableID); if (is_finite($wert) && $wert >= 0.0 && $wert <= 100.0) { return $wert; } } $this->setzeDiagnosewert('SDLStatus', 'Fehler: SDL-SOC muss zwischen 0 und 100 Prozent liegen.'); return null; } private function sdlAnzeigen(string $property): bool { return $this->ReadPropertyBoolean('SDLAktiv') && $this->ReadPropertyBoolean($property); } private function aktualisiereSDLStatus(): void { if (!$this->ReadPropertyBoolean('SDLAktiv')) { $this->setzeDiagnosewert('SDLStatus', 'NichtVerwendet'); return; } try { $this->aktuelleSDLLeistung(); $this->aktuelleSDLSOC(); } catch (Throwable $fehler) { $this->setzeDiagnosewert('SDLStatus', 'Fehler: ' . $fehler->getMessage()); } } private function synchronisiereSDLEnergiefluss(int $instanzID, bool $profilAktualisieren = false): void { $anzeigen = $this->sdlAnzeigen('SDLEnergieflussAnzeigen'); $variableID = $this->findeUnterobjekt('EnergieflussSDL'); if (!$anzeigen && $variableID === 0) { return; } if ($anzeigen && ($variableID === 0 || $profilAktualisieren)) { $variableID = $this->energieflussLeistungsvariable( 'EnergieflussSDL', 'Energiefluss SDL', $this->energieflussLeistungsprofil(), 635 ); } $alt = json_decode(IPS_GetProperty($instanzID, 'Config'), true, 512, JSON_THROW_ON_ERROR); if (!is_array($alt) || !array_is_list($alt)) { throw new RuntimeException('Die bestehende Energiefluss-Konfiguration ist keine Liste.'); } $neu = []; $gefunden = false; $socID = $this->aktuelleSDLSOC() !== null ? $this->GetIDForIdent('SDLSOCArchiv') : 1; foreach ($alt as $knoten) { if ((int) ($knoten['VariableID'] ?? 0) !== $variableID) { $neu[] = $knoten; } elseif ($anzeigen && !$gefunden) { $knoten['InfoVariableID'] = $socID; $neu[] = $knoten; $gefunden = true; } } if ($anzeigen && !$gefunden) { $neu[] = $this->energieflussKnoten($variableID, 'SDL / Regelenergie', 'storage', false, $socID); } if ($neu !== $alt) { IPS_SetProperty($instanzID, 'Config', json_encode($neu, JSON_THROW_ON_ERROR)); IPS_ApplyChanges($instanzID); } } private function synchronisiereSDLDiagramm(int $medienID, bool $energie): void { $idents = $energie ? ['SDLLadenEnergie', 'SDLEntladenEnergie', 'SDLSOCArchiv'] : ['SDLLeistungArchiv', 'SDLSOCArchiv']; $verwaltet = array_map(fn (string $ident): int => $this->GetIDForIdent($ident), $idents); $gewuenscht = []; if ($this->sdlAnzeigen('SDLDiagrammeAnzeigen')) { if ($energie) { $gewuenscht[] = $this->chartDatensatz( 'SDLLadenEnergie', 'SDL laden', '#007C91', '~Electricity', 'bar' ); $gewuenscht[] = $this->chartDatensatz( 'SDLEntladenEnergie', 'SDL entladen', '#C43E1C', '~Electricity', 'bar' ); } else { $gewuenscht[] = $this->chartDatensatz( 'SDLLeistungArchiv', 'SDL Istleistung', '#007C91', '~Power' ); } if ($this->ReadPropertyInteger('SDLSOCVariableID') > 0) { $soc = $this->chartDatensatz('SDLSOCArchiv', 'SDL SOC', '#C43E1C', '~Intensity.100'); $soc['side'] = 'right'; $gewuenscht[] = $soc; } } $inhalt = json_decode((string) base64_decode(IPS_GetMediaContent($medienID), true), true); if (!is_array($inhalt) || !isset($inhalt['datasets']) || !is_array($inhalt['datasets'])) { if (!$this->sdlAnzeigen('SDLDiagrammeAnzeigen')) { return; } throw new RuntimeException('Das bestehende Diagramm hat keine gueltigen Datensaetze.'); } $alt = $inhalt['datasets']; $neu = []; foreach ($alt as $datensatz) { $id = (int) ($datensatz['variableID'] ?? 0); if (!in_array($id, $verwaltet, true)) { $neu[] = $datensatz; continue; } foreach ($gewuenscht as $index => $ziel) { if ($id === $ziel['variableID']) { $neu[] = $datensatz; unset($gewuenscht[$index]); break; } } } $neu = array_merge($neu, array_values($gewuenscht)); if ($neu !== $alt) { $inhalt['datasets'] = $neu; IPS_SetMediaContent($medienID, base64_encode(json_encode($inhalt, JSON_THROW_ON_ERROR))); } } }