RegisterPropertyInteger("Peakleistung", 0); $this->RegisterPropertyInteger("Ueberschussleistung", 0); $this->RegisterPropertyInteger("Netzbezug", 0); // Initialisierung mit 0 $this->RegisterPropertyString("Verbraucher_Liste", "[]"); // Timer registrieren $this->RegisterTimer("Timer_DistributeEnergy",5000,"IPS_RequestAction(" .$this->InstanceID .', "DistributeEnergy", "");'); } public function ApplyChanges() { parent::ApplyChanges(); //Liste aller Verbraucher einlesen } public function RequestAction($Ident, $Value) { switch ($Ident) { case "DistributeEnergy": $this->DistributeEnergy(); break; case "ApplyChanges": $this->ApplyChanges(); break; default: throw new Exception("Invalid Ident"); } } public function DistributeEnergy() { $Verbraucher_Liste = json_decode($this->ReadPropertyString("Verbraucher_Liste"), true); $currentTime = time(); $Netzbezug = 0; $Verbraucher_Liste_Korr = []; foreach ($Verbraucher_Liste as $user) { $decodedUser = json_decode(GetValue($user["User_Up"]), true)[0]; if (isset($decodedUser["Timestamp"]) && (($currentTime - $decodedUser["Timestamp"])) < 30) { foreach ($decodedUser["Users"] as $subuser) { $subuser['Writeback'] = $user["User_Down"]; $Verbraucher_Liste_Korr[0]["User"][] = $subuser; } $Netzbezug += $decodedUser["Netzbezug"]; } } $Peakleistung = $this->ReadPropertyInteger("Peakleistung"); $Ueberschussleistung = $this->ReadPropertyInteger("Ueberschussleistung"); $Is_Peak_Shaving = false; // Fallunterscheidung ob auf Solarladen oder Peakshaving gerregelt wird. if ($Netzbezug < ($Peakleistung - $Ueberschussleistung) / 2) { $remainingPower = -1 * (-1 * $Ueberschussleistung + $Netzbezug); $Is_Peak_Shaving = false; } else { $remainingPower = $Peakleistung - $Netzbezug; $Is_Peak_Shaving = true; } $resultArray = []; // Alle Energieverbraucher auslesen und dekodieren if (empty($Verbraucher_Liste_Korr[0]["User"])) { // Liste ist leer, daher nichts zu tun IPS_LogMessage("Manager", "aufgerufen leere liste"); return; } $allIdle = true; // Variable zur Überprüfung, ob alle Benutzer Idle = true sind $totalAktuelle_Leistung = 0; // Variable zur Summierung der Aktuelle_Leistung Werte // Fülle das Array mit allen entsprechenden Werten der Verbraucher ab foreach ($Verbraucher_Liste_Korr[0]["User"] as $user) { // Überprüfen, ob alle Benutzer Idle = true sind, wenn einer nicht ist, wird später verworfen... if (!$user["Idle"]) { $allIdle = false; IPS_LogMessage("Manager", "nciht idle"); } // Addiere die aktuell bereits verwendete Leistung auf, um sie bei der verteilung zu berücksichtigen $totalAktuelle_Leistung += $user["Aktuelle_Leistung"]; } // Berücksichtigung der bereits verteilten Leistungen (nachher kann dafür wieder bei 0 begonnen werden zu verteilen) $remainingPower += $totalAktuelle_Leistung; // Wenn nicht alle Benutzer Idle = true sind, rufe SetAktuelle_Leistung mit Aktuelle_Leistung Werten auf, (alle Verbraucher behalten die aktuelle Leistung) if (!$allIdle) { // Schritt 1: Benutzer nach Writeback-Wert aufteilen $writebackArrays = []; foreach ($Verbraucher_Liste_Korr[0]["User"] as $user) { $writeback = $user['Writeback']; IPS_LogMessage("Manager", $writeback); if (!isset($writebackArrays[$writeback])) { $writebackArrays[$writeback] = []; } $writebackArrays[$writeback][] = $user; } // Schritt 2: Foreach-Schleife pro Writeback-Array foreach ($writebackArrays as $writeback => $users) { $resultArray = [ 'timestamp' => time(), 'Is_Peak_Shaving' => $Is_Peak_Shaving, 'User' => [] ]; foreach ($users as $user) { $resultArray['User'][] = [ 'InstanceID' => $user['InstanceID'], 'Set_Leistung' => $user['Aktuelle_Leistung'] ]; } // Schritt 3: Array in String konvertieren $resultString = json_encode($resultArray); // Schritt 4: RequestAction aufrufen RequestAction($writeback, $resultString); } return; } // Sortiere die Verbruacher nach Priorität entweder der PV_Prio oder der Peak Prio usort($Verbraucher_Liste_Korr[0]["User"], function ($a, $b) use ( $Is_Peak_Shaving ) { $primaryKey = $Is_Peak_Shaving ? "Sperre_Prio" : "PV_Prio"; // Wenn die Prio geleich ist, sortiere danach welcher verbraucher bisher am wenigsten Energie bekommen hat. if ($a[$primaryKey] == $b[$primaryKey]) { return $a["Bezogene_Energie"] <=> $b["Bezogene_Energie"]; } return $a[$primaryKey] <=> $b[$primaryKey]; }); // Primärschlüssel für die Priorität basierend auf dem Parameter auswählen (für sortierung in gruppen anschliessend) $priorityKey = $Is_Peak_Shaving ? "Sperre_Prio" : "PV_Prio"; // Schleife durch alle Prioritäten $priorities = array_unique( array_column($Verbraucher_Liste_Korr[0]["User"], $priorityKey) ); $groupedUsers = []; foreach ($priorities as $priority) { $groupedUsers[$priority] = array_filter( $Verbraucher_Liste_Korr[0]["User"], function ($user) use ($priority, $priorityKey) { return $user[$priorityKey] == $priority; } ); } // Jetzt werden die energien pro gruppe verteilt (Immer alle pro prio in einer gruppe miteinander) foreach ($groupedUsers as $priority => $users) { // Verbraucher mit gleicher Priorität sammeln $samePriorityUsers = isset($groupedUsers[$priority]) ? $groupedUsers[$priority] : []; // Wenn keine Verbraucher mit gleicher Priorität vorhanden sind, überspringen if (empty($samePriorityUsers)) { continue; } $withZero = []; $withoutZero = []; // Verbraucher die nicht 0 Annhemen können, bekommen einfach den tiefsten wert foreach ($samePriorityUsers as $entry) { if (min($entry["PowerSteps"]) <= 0) { $withZero[] = $entry; } else { $withoutZero[] = $entry; } } // Verbraucher die nicht 0 annhemen können erhalten nun den minimalwert if (!empty($withoutZero)) { foreach ($withoutZero as $entry) { $resultArray[] = [ 'user' => $user['InstanceID'], 'Writeback' => $user['Writeback'], 'Set_Leistung' => min($entry["PowerSteps"]) ]; $remainingPower -= $entry["Aktuelle_Leistung"]; } } // Nun die verteilen, die 0 erhalten können. $samePriorityUsers = $withZero; // Array für die verteilte Energie pro User erstellen $userEnergyProv = []; foreach ($samePriorityUsers as $user) { $userEnergyProv[$user['InstanceID']] = [ 'user' => $user['InstanceID'], 'Writeback' => $user['Writeback'], 'Set_Leistung' => 0 ]; } // Alle Schritte der Benutzer in einem Array sammeln $allSteps = []; foreach ($samePriorityUsers as $user) { foreach ($user["PowerSteps"] as $step) { $allSteps[] = [ "user" => $user["InstanceID"], "Writeback" => $user["Writeback"], "step" => $step, ]; } } // Sortiere die Schritte nach Größe usort($allSteps, function ($a, $b) { return $a["step"] <=> $b["step"]; }); // Iteriere durch alle Schritte foreach ($allSteps as $entry) { $user = $entry["user"]; $manager = $entry["Writeback"]; $powerstep = $entry["step"]; $aktleistung = array_filter($userEnergyProv, function($entry2) use ($user, $manager) { return $entry2["user"] == $user && $entry2["Writeback"] == $manager; }); foreach($aktleistung as $entry){ $aktleistung = $entry; } // Überprüfe, ob noch genügend verbleibende Energie für den nächsten Schritt vorhanden ist if ($remainingPower >= $powerstep - $aktleistung['Set_Leistung']) { // Aktualisiere die verbleibende Energie und die bereitgestellte Energie für den Benutzer $remainingPower -= $powerstep - $aktleistung['Set_Leistung']; array_walk($userEnergyProv, function(&$entry3) use ($user, $manager, $powerstep) { if ($entry3["user"] == $user && $entry3["Writeback"] == $manager) { $entry3["Set_Leistung"] = $powerstep; } }); } } // Prüfen, dass jeder User mindestens seinen minimalwert an Leistung bekommt foreach ($userEnergyProv as $userInstanceID => $leistung) { $minimalleitsung = min( array_column( array_filter($allSteps, function ($entry) use ( $userInstanceID ) { return $entry["user"] == $userInstanceID; }), "step" ) ); // Jedem user den höheren der beiden werte aus minimalwert oder vergebenem zuteilen $leistung = max($leistung, $minimalleitsung); // Methode SetAktuelle_Leistung für jeden Verbraucher mit der entsprechenden Energie aufrufen $resultArray[] = $userEnergyProv[$userInstanceID]; //[ // 'InstanceID' => $user['InstanceID'], // 'Writeback' => $user['Writeback'], // 'Set_Leistung' => $leistung // ]; } } IPS_LogMessage("Manager", print_r($resultArray)); $writebackArrays = []; foreach ($resultArray as $user) { $writeback = $user['Writeback']; if (!isset($writebackArrays[$writeback])) { $writebackArrays[$writeback] = []; } $writebackArrays[$writeback][] = $user; } // Schritt 2: Foreach-Schleife pro Writeback-Array foreach ($writebackArrays as $writeback => $users) { $resultArray = [ 'timestamp' => time(), 'Is_Peak_Shaving' => $Is_Peak_Shaving, 'User' => [] ]; foreach ($users as $user) { $resultArray['User'][] = [ 'InstanceID' => $user['user'], 'Set_Leistung' => $user['Set_Leistung'] ]; } // Schritt 3: Array in String konvertieren $resultString = json_encode($resultArray); // Schritt 4: RequestAction aufrufen RequestAction($writeback, $resultString); } } } ?>