RegisterPropertyInteger("Peakleistung", 0); $this->RegisterPropertyInteger("Ueberschussleistung", 0); $this->RegisterPropertyInteger("Netzbezug", 0); // Initialisierung mit 0 $this->RegisterPropertyString("Verbraucher_Liste", "[]"); $this->RegisterPropertyBoolean("HauptmanagerAktiv", false); // Initialisierung mit 0 $this->RegisterPropertyInteger("ManagerID", 0); // Initialisierung mit 0 $this->RegisterPropertyInteger("DatenHoch", 0); // Initialisierung mit 0 $this->RegisterPropertyInteger("DatenZuruck", 0); // Initialisierung mit 0 $this->RegisterPropertyInteger("Interval", 2); // Recheninterval // Timer registrieren $this->RegisterTimer("Timer_DistributeEnergy",$this->ReadPropertyInteger("Interval")*1000,"IPS_RequestAction(" .$this->InstanceID .', "DistributeEnergy", "");'); } public function ApplyChanges() { parent::ApplyChanges(); $this->SetTimerInterval("Timer_DistributeEnergy",$this->ReadPropertyInteger("Interval")*1000); } public function RequestAction($Ident, $Value) { switch ($Ident) { case "DistributeEnergy": if($this->ReadPropertyBoolean("HauptmanagerAktiv")==true ){ $data = json_decode(GetValue($this->ReadPropertyInteger("DatenZuruck")), true); IPS_LogMessage("Manager", print_r($data)); IPS_LogMessage("Manager", $data["timestamp"]); if (isset($data["timestamp"])) { $timestamp = $data["timestamp"]; $currentTime = time(); IPS_LogMessage("Manager", ($currentTime - $timestamp)); if (($currentTime - $timestamp) < 3600) { $this->DistributeEnergy_Extern(); } } else { $this->DistributeEnergy(); } }else{ $this->DistributeEnergy(); } break; case "ApplyChanges": $this->ApplyChanges(); break; default: throw new Exception("Invalid Ident"); } } public function DistributeEnergy() { // Systemvariablen abrufen $Netzbezug = GetValue($this->ReadPropertyInteger("Netzbezug")); $Peakleistung = $this->ReadPropertyInteger("Peakleistung"); $Ueberschussleistung = $this->ReadPropertyInteger("Ueberschussleistung"); // 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; } IPS_LogMessage("Manag anfang", $remainingPower); // Alle Energieverbraucher auslesen und dekodieren $Verbraucher_Liste = json_decode($this->ReadPropertyString("Verbraucher_Liste"), true); if (empty($Verbraucher_Liste)) { // Liste ist leer, daher nichts zu tun IPS_LogMessage("Manager", "aufgerufen leere liste"); return; } // Frage alle Energieverbraucher ab, was sie für Leistungen benötigen könnten foreach ($Verbraucher_Liste as $user) { if (IPS_InstanceExists($user["Verbraucher"])) { IPS_RequestAction($user["Verbraucher"],"GetCurrentData", $Is_Peak_Shaving); IPS_LogMessage("Manager", "aufgerufen getcurrentdata"); } } $filteredVerbraucher = []; // Array das später mit allen Verbrauchsdaten der Energieverbraucher gefüllt wird $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 as $user) { if (!IPS_InstanceExists($user["Verbraucher"])) { IPS_LogMessage("Manager", "aufgerufen komisch"); continue; } $idle = GetValue(IPS_GetObjectIDByIdent("Idle", $user["Verbraucher"])); $powerStepsJson = GetValue(IPS_GetObjectIDByIdent("PowerSteps", $user["Verbraucher"])); $powerSteps = json_decode($powerStepsJson, true); // Verbraucher-Daten zum gefilterten Array hinzufügen $filteredVerbraucher[] = [ "InstanceID" => $user["Verbraucher"], "Aktuelle_Leistung" => GetValue(IPS_GetObjectIDByIdent("Power", $user["Verbraucher"])), "Bezogene_Energie" => GetValue(IPS_GetObjectIDByIdent("Bezogene_Energie", $user["Verbraucher"])), "PV_Prio" => GetValue(IPS_GetObjectIDByIdent("PV_Prio", $user["Verbraucher"])), "Sperre_Prio" => GetValue(IPS_GetObjectIDByIdent("Sperre_Prio", $user["Verbraucher"])), "Idle" => $idle, "PowerSteps" => $powerSteps, "Leistung_Delta" => GetValue(IPS_GetObjectIDByIdent("Leistung_Delta", $user["Verbraucher"])) ]; // Überprüfen, ob alle Benutzer Idle = true sind, wenn einer nicht ist, wird später verworfen... if (!$idle) { $allIdle = false; IPS_LogMessage("Manager", "nciht idle"); } if(in_array(0, $powerSteps, true)){ // Addiere die aktuell bereits verwendete Leistung auf, um sie bei der verteilung zu berücksichtigen $totalAktuelle_Leistung += (GetValue(IPS_GetObjectIDByIdent("Power", $user["Verbraucher"])) + GetValue(IPS_GetObjectIDByIdent("Leistung_Delta", $user["Verbraucher"]))); } } // Berücksichtigung der bereits verteilten Leistungen (nachher kann dafür wieder bei 0 begonnen werden zu verteilen) $remainingPower += $totalAktuelle_Leistung; // Abbrechen wenn es keine gefilterten User gibt if (empty($filteredVerbraucher)) { return; } // Wenn nicht alle Benutzer Idle = true sind, rufe SetAktuelle_Leistung mit Aktuelle_Leistung Werten auf, (alle Verbraucher behalten die aktuelle Leistung) if (!$allIdle) { foreach ($filteredVerbraucher as $user) { IPS_RequestAction($user["InstanceID"],"SetAktuelle_Leistung",$user["Aktuelle_Leistung"]); IPS_LogMessage("Manager", "aufgerufen nicht alle idle"); } return; } // Sortiere die Verbruacher nach Priorität entweder der PV_Prio oder der Peak Prio usort($filteredVerbraucher, 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 round($a["Bezogene_Energie"]/2000) <=> round($b["Bezogene_Energie"]/2000); } 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($filteredVerbraucher, $priorityKey) ); $groupedUsers = []; foreach ($priorities as $priority) { $groupedUsers[$priority] = array_filter( $filteredVerbraucher, 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) { $instanceID = $entry["InstanceID"]; $minPowerStep = min($entry["PowerSteps"]); IPS_RequestAction($instanceID,"SetAktuelle_Leistung",$minPowerStep); //$remainingPower -= $entry["Aktuelle_Leistung"]; } } // Nun die verteilen, die 0 erhalten können. $samePriorityUsers = $withZero; $userEnergyProv = []; $userEnergyProv = array_fill_keys(array_column($samePriorityUsers, "InstanceID"), 0); // Initialisierung für jeden Benutzer auf 0 setzen IPS_LogMessage("Manag", $remainingPower); $help_state = false; if($remainingPower>=0){ $help_state = true; } // Alle Schritte der Benutzer in einem Array sammeln $allSteps = []; foreach ($samePriorityUsers as $user) { foreach ($user["PowerSteps"] as $step) { if($help_state==true){ if($step>=0){ $allSteps[] = [ "user" => $user["InstanceID"], "step" => $step ]; } } else{ if($step<=0){ $allSteps[] = [ "user" => $user["InstanceID"], "step" => -1*$step ]; } } } } // Sortiere die Schritte nach Größe usort($allSteps, function ($a, $b) { return $a["step"] <=> $b["step"]; }); if($help_state==false){ $remainingPower = $remainingPower *-1; } foreach ($allSteps as $entry) { $user = $entry["user"]; $powerstep = $entry["step"]; // Überprüfe, ob noch genügend verbleibende Energie für den nächsten Schritt vorhanden ist if ($remainingPower >= $powerstep - $userEnergyProv[$user]) { // oder bedingung testen // Aktualisiere die verbleibende Energie und die bereitgestellte Energie für den Benutzer $remainingPower -= $powerstep - $userEnergyProv[$user]; $userEnergyProv[$user] = $powerstep; } } if($help_state==false){ $remainingPower = $remainingPower *-1; } // 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 $schreibleistung = max($leistung, $minimalleitsung) * ($help_state ? 1 : -1); // Methode SetAktuelle_Leistung für jeden Verbraucher mit der entsprechenden Energie aufrufen if (IPS_InstanceExists($userInstanceID)) { IPS_RequestAction($userInstanceID,"SetAktuelle_Leistung",$schreibleistung); IPS_LogMessage("Manager", "aufgerufen setleistung else ".$schreibleistung); } } } } public function DistributeEnergy_Extern() { // Systemvariablen abrufen $Netzbezug = GetValue($this->ReadPropertyInteger("Netzbezug")); $Verbraucher_Liste = json_decode($this->ReadPropertyString("Verbraucher_Liste"), true); $filteredVerbraucher = []; // Fülle das Array mit allen entsprechenden Werten der Verbraucher ab foreach ($Verbraucher_Liste as $user) { // Verbraucher-Daten zum gefilterten Array hinzufügen $filteredVerbraucher[] = [ "InstanceID" => $user["Verbraucher"], "Aktuelle_Leistung" => GetValue(IPS_GetObjectIDByIdent("Power", $user["Verbraucher"])), "Bezogene_Energie" => GetValue(IPS_GetObjectIDByIdent("Bezogene_Energie", $user["Verbraucher"])), "PV_Prio" => GetValue(IPS_GetObjectIDByIdent("PV_Prio", $user["Verbraucher"])), "Sperre_Prio" => GetValue(IPS_GetObjectIDByIdent("Sperre_Prio", $user["Verbraucher"])), "Idle" => GetValue(IPS_GetObjectIDByIdent("Idle", $user["Verbraucher"])), "PowerSteps" => json_decode(GetValue(IPS_GetObjectIDByIdent("PowerSteps", $user["Verbraucher"])), true), "Leistung_Delta" => GetValue(IPS_GetObjectIDByIdent("Leistung_Delta", $user["Verbraucher"])), "ParentManager" => $this->ReadPropertyInteger("ManagerID") ]; } $sendarray = []; $sendarray = [ "Users" => $filteredVerbraucher, "Netzbezug" => $Netzbezug, "Timestamp" => time() ]; RequestAction($this->ReadPropertyInteger("DatenHoch"), json_encode($sendarray)); $answerArray = json_decode(GetValue($this->ReadPropertyInteger("DatenZuruck")), true); foreach($answerArray["User"] as $user){ IPS_RequestAction($user["InstanceID"],"GetCurrentData", $answerArray["Is_Peak_Shaving"]); IPS_RequestAction($user["InstanceID"],"SetAktuelle_Leistung",$user["Set_Leistung"]); } } } ?>