diff --git a/Batterie/form.json b/Batterie/form.json index b203cf2..c565e46 100644 --- a/Batterie/form.json +++ b/Batterie/form.json @@ -85,6 +85,10 @@ "type": "SelectVariable", "name": "Netzbezug", "caption": "Variable mit dem zu regelnden Netzbezug" + }, + { + "type": "Label", + "caption": "Goodwe: Laden=11, Entladen=12,\nSolaredge: Laden=3, Entladen=4,\nSig Energy: Laden=3, Entladen=6, P in kW" } ] } diff --git a/Batterie/module.php b/Batterie/module.php index 73efa65..c497a1c 100644 --- a/Batterie/module.php +++ b/Batterie/module.php @@ -23,10 +23,9 @@ class Batterie extends IPSModule $this->RegisterVariableFloat("Entladeleistung","Entladeleistung", "",0); $this->RegisterVariableInteger("Batteriemanagement_Variabel","Batteriemanagement_Variabel", "",0); //$this->RegisterVariableInteger("Laden3_Entladen4","Laden3_Entladen4", "",3); - $this->RegisterVariableInteger("Laden_Entladen","Laden_Entladen", "",3); - $this->RegisterVariableString("Laden_Entladen_Beschreibung","{Goodwe: Laden=11, Entladen=12}, {Solaredge: Laden=3, Entladen=4},{Sig Energy: Laden=3, Entladen=6, P in kW}", "",0); + //$this->RegisterVariableInteger("Laden_Entladen","Laden_Entladen", "",3); $this->RegisterVariableFloat("Ladeleistung","Ladeleistung", "",0); - $this->RegisterVariableFloat("Goodwe_EntLadeleistung","Goodwe_EntLadeleistung", "",0); + //$this->RegisterVariableFloat("Goodwe_EntLadeleistung","Goodwe_EntLadeleistung", "",0); $this->RegisterVariableInteger("Aktuelle_Leistung", "Aktuelle_Leistung", "", 0); $this->RegisterVariableString("PowerSteps", "PowerSteps"); $this->RegisterVariableBoolean("Idle", "Idle", "", 0); @@ -59,11 +58,26 @@ class Batterie extends IPSModule { parent::ApplyChanges(); - - $batterieManagement = $this->ReadPropertyInteger("Batteriemanagement"); $this->SetValue("Batteriemanagement_Variabel", $batterieManagement); $this->SetTimerInterval("Timer_Do_UserCalc_Battery",$this->ReadPropertyInteger("Interval")*1000); + + switch ($batterietyp) { + case 1: // z.B. LiFePo4 + $this->RegisterVariableFloat("Goodwe_EntLadeleistung","Goodwe_EntLadeleistung", "",0); + break; + + case 2: // z.B. Blei-Gel + + break; + + case 3: + + break; + } + + + } diff --git a/Batterie_test/README.md b/Batterie_test/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Batterie_test/form.json b/Batterie_test/form.json new file mode 100644 index 0000000..c565e46 --- /dev/null +++ b/Batterie_test/form.json @@ -0,0 +1,94 @@ +{ + "elements": [ + { + "type": "Label", + "caption": "Konfiguration der Batterie für Peakshaving" + }, + { + "type": "NumberSpinner", + "name": "IdleCounterMax", + "caption": "Zyklen zwischen zwei Leistungsänderungen (Multipliziert sich mit Interval)", + "suffix": "" + }, + { + "type": "NumberSpinner", + "name": "Interval", + "caption": "Intervall Neuberechnung der Werte", + "suffix": "Sekunden" + }, + { + "type":"Select", + "name":"Batterietyp", + "caption":"Batterietyp", + "options":[ + { + "caption":"Goodwe", + "value":1 + }, + { + "caption":"Solaredge", + "value":2 + }, + { + "caption":"Sig Energy", + "value":3 + } + ] + }, + { + "type": "NumberSpinner", + "name": "MaxBatterieleistung", + "caption": "Maximale Batterieleistung", + "suffix": "" + }, + { + "type": "NumberSpinner", + "name": "MaxNachladen", + "caption": "Maximum Nachladen", + "suffix": "" + }, + { + "type": "NumberSpinner", + "name": "AufdasNachladen", + "caption": "Auf so viel Prozent nachladen", + "suffix": "" + + }, + { + "type": "NumberSpinner", + "name": "MinimumEntladen", + "caption": "Minimum des Batterieladezustand", + "suffix": "" + }, + { + "type":"Select", + "name":"Batteriemanagement", + "caption":"Batteriemanagement", + "options":[ + { + "caption":"Durch Wechselrichter", + "value":1 + }, + { + "caption":"Durch EMS Symcon", + "value":2 + } + ] + }, + { + "type": "SelectVariable", + "name": "Batterieladezustand", + "caption": "Batterieladezustand", + "test": true + }, + { + "type": "SelectVariable", + "name": "Netzbezug", + "caption": "Variable mit dem zu regelnden Netzbezug" + }, + { + "type": "Label", + "caption": "Goodwe: Laden=11, Entladen=12,\nSolaredge: Laden=3, Entladen=4,\nSig Energy: Laden=3, Entladen=6, P in kW" + } + ] +} diff --git a/Batterie_test/module.json b/Batterie_test/module.json new file mode 100644 index 0000000..62fce35 --- /dev/null +++ b/Batterie_test/module.json @@ -0,0 +1,12 @@ +{ + "id": "{A7FEA6E1-EBAA-1567-C14B-9A63B09C9EDC}", + "name": "Batterie_test", + "type": 3, + "vendor": "Belevo AG", + "aliases": [], + "parentRequirements": [], + "childRequirements": [], + "implemented": [], + "prefix": "GEF", + "url": "" +} \ No newline at end of file diff --git a/Batterie_test/module.php b/Batterie_test/module.php new file mode 100644 index 0000000..e034879 --- /dev/null +++ b/Batterie_test/module.php @@ -0,0 +1,453 @@ +RegisterPropertyInteger("MaxBatterieleistung", 0); + $this->RegisterPropertyInteger("Batteriespannung", 50); + $this->RegisterPropertyInteger("AufdasNachladen",0); + $this->RegisterPropertyInteger("MinimumEntladen",0); + $this->RegisterPropertyInteger("Batterieladezustand",0); + $this->RegisterPropertyInteger("Batteriemanagement", 1); + $this->RegisterPropertyInteger("Batterietyp", 1); + $this->RegisterPropertyInteger("MaxNachladen",0); + $this->RegisterPropertyInteger("Netzbezug", 0); // Initialisierung mit 0 + $this->RegisterPropertyInteger("Interval", 2); // Recheninterval + + + // Variabeln für Kommunkation mit Manager + $this->RegisterVariableFloat("Entladeleistung","Entladeleistung", "",0); + $this->RegisterVariableInteger("Batteriemanagement_Variabel","Batteriemanagement_Variabel", "",0); + //$this->RegisterVariableInteger("Laden3_Entladen4","Laden3_Entladen4", "",3); + $this->RegisterVariableInteger("Laden_Entladen","Laden_Entladen", "",3); + $this->RegisterVariableFloat("Ladeleistung","Ladeleistung", "",0); + $this->RegisterVariableFloat("Goodwe_EntLadeleistung","Goodwe_EntLadeleistung", "",0); + $this->RegisterVariableInteger("Aktuelle_Leistung", "Aktuelle_Leistung", "", 0); + $this->RegisterVariableString("PowerSteps", "PowerSteps"); + $this->RegisterVariableBoolean("Idle", "Idle", "", 0); + $this->RegisterVariableInteger("Sperre_Prio", "Sperre_Prio"); + $this->RegisterVariableInteger("PV_Prio", "PV_Prio"); + $this->RegisterVariableInteger("Power", "Power"); + $this->RegisterVariableBoolean("Is_Peak_Shaving", "Is_Peak_Shaving"); + $this->RegisterVariableInteger("Leistung_Delta", "Leistung_Delta", "", 0); + + $this->RegisterVariableBoolean("Hysterese", "Hysterese","",false); + + + + $this->RegisterVariableFloat("Bezogene_Energie", "Bezogene_Energie", "", 0); + + // Hilfsvariabeln für Idle zustand + $this->RegisterPropertyInteger("IdleCounterMax", 2); + $this->RegisterVariableInteger("IdleCounter", "IdleCounter", "", 0); + $this->SetValue("IdleCounter", 0); + + // Initialisiere Idle + $this->SetValue("Idle", true); + + $this->RegisterTimer("Timer_Do_UserCalc_Battery",$this->ReadPropertyInteger("Interval")*1000,"IPS_RequestAction(" .$this->InstanceID .', "Do_UserCalc", "");'); + + + } + + public function ApplyChanges() + { + parent::ApplyChanges(); + + $batterieManagement = $this->ReadPropertyInteger("Batteriemanagement"); + $this->SetValue("Batteriemanagement_Variabel", $batterieManagement); + $this->SetTimerInterval("Timer_Do_UserCalc_Battery",$this->ReadPropertyInteger("Interval")*1000); + + + + + + } + + + private function GeneratePowerSteps($additionalValue) + { + $maxleistung = $this->ReadPropertyInteger("MaxBatterieleistung"); + $stepSize = 250; // Schrittgröße + $stepSizeSmall = 50; // Kleine Schrittgröße + + // Array direkt als Range erzeugen (schneller als Schleife) + $array_powersteps = range(-$maxleistung, $maxleistung, $stepSize); + + // Nächstgelegenen Wert direkt bestimmen (rundet auf den nächsten Step) + $closestValue = round($additionalValue / $stepSize) * $stepSize; + + // Falls der Wert nicht im Bereich liegt, abbrechen + if (!in_array($closestValue, $array_powersteps)) { + return $array_powersteps; + } + + // Index des gefundenen Werts suchen + $index = array_search($closestValue, $array_powersteps); + + // Zusätzliche Werte berechnen und auf MaxLeistung begrenzen + $newValues = array_filter([ + $closestValue - 4 * $stepSizeSmall, + $closestValue - 3 * $stepSizeSmall, + $closestValue - 2 * $stepSizeSmall, + $closestValue - $stepSizeSmall, + $closestValue, + $closestValue + $stepSizeSmall, + $closestValue + 2 * $stepSizeSmall, + $closestValue + 3 * $stepSizeSmall, + $closestValue + 4 * $stepSizeSmall, + ], function ($value) use ($maxleistung) { + return $value >= -$maxleistung && $value <= $maxleistung; + }); + + // Effizienteres Einfügen der Werte (direkt an der Stelle) + array_splice($array_powersteps, $index, 1, $newValues); + + return $array_powersteps; + } + + + + +public function RequestAction($Ident, $Value) +{ + switch ($Ident) { + + case "SetAktuelle_Leistung": + $this->SetValue("Power", (int)$Value); + break; + + case "GetCurrentData": + $this->SetValue("Is_Peak_Shaving", (bool)$Value); + break; + + + case "Do_UserCalc": + + $this->SetAktuelle_Leistung($this->GetValue("Power")); + $this->GetCurrentData($this->GetValue("Is_Peak_Shaving")); + break; + + default: + throw new Exception("Invalid Ident"); + } +} + + public function SetAktuelle_Leistung(int $power) + { + + + $batterietyp = $this->ReadPropertyInteger("Batterietyp"); + $batterieManagement = $this->ReadPropertyInteger("Batteriemanagement"); + + // Goodwe, Solaredge WR Modus + if ($batterieManagement == 1 && ($batterietyp == 1 || $batterietyp == 2)) { + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Ladeleistung", 0); + $this->SetValue("Batteriemanagement_Variabel", 1); + return; + //Sig Energy WR Modus + } elseif ($batterieManagement == 1 && $batterietyp == 3) { + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Ladeleistung", 0); + $this->SetValue("Batteriemanagement_Variabel", 0); + return; + + // Sig Energy Symcon Modus + } elseif ($batterieManagement == 2 && $batterietyp == 3) { + $this->SetValue("Batteriemanagement_Variabel", 1); + + //Solaredge Symcon Modus + }elseif ($batterieManagement == 2 && $batterietyp == 2) { + $this->SetValue("Batteriemanagement_Variabel", 4); + } + /* + if($this->GetValue("Is_Peak_Shaving")==true){ + if ($power >= 0) { + $this->SetValue("Ladeleistung", $power); + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Laden3_Entladen4", 3); + } else { + $this->SetValue("Entladeleistung", abs($power)); + $this->SetValue("Ladeleistung", 0); + $this->SetValue("Laden3_Entladen4", 4); + } + + }else{ + if ($power >= 0) { + $this->SetValue("Ladeleistung", $power); + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Laden3_Entladen4", 3); + } else { + $this->SetValue("Entladeleistung", abs($power)); + $this->SetValue("Ladeleistung", 0); + $this->SetValue("Laden3_Entladen4", 4); + } + + } + */ + + + + + + + $batterietyp = $this->ReadPropertyInteger("Batterietyp"); + if ($batterietyp == 1) {//Goodwe + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Ladeleistung", 0); + //-----------------------Gooodwee-------------------------------------// + if($this->GetValue("Is_Peak_Shaving")==true){ + + if ($power >= 0) { + $this->SetValue("Goodwe_EntLadeleistung", abs($power)); + $this->SetValue("Laden_Entladen", 11); + } else { + $this->SetValue("Goodwe_EntLadeleistung", abs($power)); + $this->SetValue("Laden_Entladen", 12); + } + + }else{ + + if ($power >= 0) { + $this->SetValue("Goodwe_EntLadeleistung", abs($power)); + $this->SetValue("Laden_Entladen", 11); + } else { + $this->SetValue("Goodwe_EntLadeleistung", abs($power)); + $this->SetValue("Laden_Entladen", 12); + } + + } + + }elseif ($batterietyp == 2) {//Solaredge + + //-----------------------Solaredge-------------------------------------// + $this->SetValue("Goodwe_EntLadeleistung",0); + if($this->GetValue("Is_Peak_Shaving")==true){ + + if ($power >= 0) { + $this->SetValue("Ladeleistung", $power); + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Laden_Entladen", 3); + } else { + $this->SetValue("Entladeleistung", abs($power)); + $this->SetValue("Ladeleistung", 0); + $this->SetValue("Laden_Entladen", 4); + } + + }else{ + if ($power >= 0) { + $this->SetValue("Ladeleistung", $power); + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Laden_Entladen", 3); + } else { + $this->SetValue("Entladeleistung", abs($power)); + $this->SetValue("Ladeleistung", 0); + $this->SetValue("Laden_Entladen", 4); + } + } + } elseif ($batterietyp == 3) {//Sig Energy + + //-----------------------Sig Energy-------------------------------------// + $this->SetValue("Goodwe_EntLadeleistung",0); + if($this->GetValue("Is_Peak_Shaving")==true){ + + if ($power >= 0) { + $this->SetValue("Ladeleistung", $power/1000); + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Laden_Entladen", 3); + } else { + $this->SetValue("Entladeleistung", abs($power)/1000); + $this->SetValue("Ladeleistung", 0); + $this->SetValue("Laden_Entladen", 6); + } + + }else{ + if ($power >= 0) { + $this->SetValue("Ladeleistung", $power/1000); + $this->SetValue("Entladeleistung", 0); + $this->SetValue("Laden_Entladen", 3); + } else { + $this->SetValue("Entladeleistung", abs($power)/1000); + $this->SetValue("Ladeleistung", 0); + $this->SetValue("Laden_Entladen", 6); + } + } + } + + + + + + + + + + + + + + // Prüfe auf Änderung der Leistung im Vergleich zur letzten Einstellung + $lastPower = GetValue($this->GetIDForIdent("Aktuelle_Leistung")); + if ($power != $lastPower) { + $this->SetValue("Idle", false); + $this->SetValue( + "IdleCounter", + $this->ReadPropertyInteger("IdleCounterMax") + ); + } + + // Setze die neue aktuelle Leistung + $this->SetValue("Aktuelle_Leistung", $power); + $this->SetValue("Bezogene_Energie", ($this->GetValue("Bezogene_Energie") + ($this->GetValue("Aktuelle_Leistung")*($this->ReadPropertyInteger("Interval")/3600)))); + + // IdleCounter verarbeiten + $this->ProcessIdleCounter(); + + + } + + + public function GetCurrentData(bool $Peak) + { + IPS_LogMessage("Batterie", "Currentdata"); + + $array_powersteps = $this->GeneratePowerSteps($this->GetValue("Aktuelle_Leistung")); + $aufdasnachladen = $this->ReadPropertyInteger("AufdasNachladen"); + $minimumentladen = $this->ReadPropertyInteger("MinimumEntladen"); + $maxleistung = $this->ReadPropertyInteger("MaxBatterieleistung"); + $dummy_array = []; + $batterieladezustand = GetValue($this->ReadPropertyInteger("Batterieladezustand")); + $filtered_powersteps_entladen = []; + if ($this->ReadPropertyInteger("Batteriemanagement") == 1) { + $dummy_array[] = 0; + return $this->SetValue("PowerSteps", json_encode($dummy_array)); + } + + $netzbezug = GetValue($this->ReadPropertyInteger("Netzbezug")); + if (abs($netzbezug) > $maxleistung) { + $netzbezug = $maxleistung * (-1); + } + + if($batterieladezustand>(5+$aufdasnachladen)){ + + $this->SetValue("Hysterese", false); + + }elseif($batterieladezustand<=$aufdasnachladen){ + $this->SetValue("Hysterese", true); + } + + $hyst = $this->GetValue("Hysterese"); + + if($Peak){ + IPS_LogMessage("Batterie", "Im if teil"); + + if($batterieladezustand>$aufdasnachladen && $hyst==false){ + + $dummy_array[] = $netzbezug; + $this->SetValue("PowerSteps", json_encode($dummy_array)); + + }elseif($batterieladezustand>$aufdasnachladen && $hyst==true){ + + + $filtered_powersteps = array_filter($array_powersteps, function ($value) { + return $value <= 0; + }); + $filtered_powersteps_laden = array_values($filtered_powersteps); + $this->SetValue("PowerSteps", json_encode($filtered_powersteps_laden)); + + }elseif($batterieladezustand>$minimumentladen){ + + $this->SetValue("PowerSteps", json_encode($array_powersteps)); + } + else{ + + $filtered_powersteps = array_filter($array_powersteps, function ($value) { + return $value >= 0; + }); + $filtered_powersteps_laden = array_values($filtered_powersteps); + $this->SetValue("PowerSteps", json_encode($filtered_powersteps_laden)); + } + + }else{ + IPS_LogMessage("Batterie", "Im else teil"); + + + if($batterieladezustand>99){ + IPS_LogMessage("Batterie", "im 1"); + + $filtered_powersteps = array_filter($array_powersteps, function ($value) { + return $value <= 0; + }); + $filtered_powersteps_laden = array_values($filtered_powersteps); + $this->SetValue("PowerSteps", json_encode($filtered_powersteps_laden)); + + }elseif($batterieladezustand>$aufdasnachladen && $hyst==false){ + + $this->SetValue("PowerSteps", json_encode($array_powersteps)); + IPS_LogMessage("Batterie", "im 2"); + + + }elseif($batterieladezustand>=$aufdasnachladen && $hyst==true){ + + $filtered_powersteps = array_filter($array_powersteps, function ($value) { + return $value >= 0; + }); + $filtered_powersteps_laden = array_values($filtered_powersteps); + $this->SetValue("PowerSteps", json_encode($filtered_powersteps_laden)); + + + }elseif($batterieladezustand<$aufdasnachladen){ + + $dummy_array[] = $this->ReadPropertyInteger("MaxNachladen"); + $this->SetValue("PowerSteps", json_encode($dummy_array)); + IPS_LogMessage("Batterie", "im 3"); + + } + + } + + } + + + + + private function CheckIdle($power) + { + $lastpower = GetValue("Aktuelle_Leistung"); + if ($lastpower != GetValue("Aktuelle_Leistung")) { + $this->SetValue("Idle", false); + $this->SetValue( + "IdleCounter", + $this->ReadPropertyInteger("IdleCounterMax") + ); + } + // IdleCounter auslesen und verarbeiten + $idleCounter = $this->GetValue("IdleCounter"); + if ($idleCounter > 0) { + $this->SetValue("Idle", false); + $this->SetValue("IdleCounter", $idleCounter - 1); + } else { + $this->SetValue("Idle", true); + } + } + + + private function ProcessIdleCounter() + { + // IdleCounter auslesen und verarbeiten + $idleCounter = $this->GetValue("IdleCounter"); + if ($idleCounter > 0) { + $this->SetValue("Idle", false); + $this->SetValue("IdleCounter", $idleCounter - 1); + } else { + $this->SetValue("Idle", true); + } + } + +} +?>