diff --git a/Bat_EV_SDL_V3_Beta/module.php b/Bat_EV_SDL_V3_Beta/module.php index 88533a4..654e513 100644 --- a/Bat_EV_SDL_V3_Beta/module.php +++ b/Bat_EV_SDL_V3_Beta/module.php @@ -697,8 +697,102 @@ private function CalculateBatteryDistribution(float $pEvW, float $pSdlW): array // $aktEV = (float)($totalPower_ist - $aktSDL); } } - $this->SetValue("Aktuelle_Leistung_EV", $aktEV); - $this->SetValue("Aktuelle_Leistung_SDL", $aktSDL); + + $filterCurrent = function(string $ch, float $raw, float $target, float $tolW, int $needHits): float { + + // Letzter akzeptierter Wert + $lastVal = (float)$this->GetBufferSafe("CUR_{$ch}_VAL"); + // Letztes Ziel (Soll), auf das wir "warten" + $pending = (float)$this->GetBufferSafe("CUR_{$ch}_PEND"); + // Counter wie oft raw im Fenster war + $hits = (int)$this->GetBufferSafe("CUR_{$ch}_HITS"); + + // Init falls leer + if ($this->GetBufferSafe("CUR_{$ch}_INIT") !== "1") { + $lastVal = $raw; // Start mit aktuellem Rohwert + $pending = $target; // erstes Ziel + $hits = 0; + $this->SetBuffer("CUR_{$ch}_INIT", "1"); + $this->SetBuffer("CUR_{$ch}_VAL", (string)$lastVal); + $this->SetBuffer("CUR_{$ch}_PEND", (string)$pending); + $this->SetBuffer("CUR_{$ch}_HITS", (string)$hits); + } + + // Wenn Soll (target) sich ändert -> neuen Pending setzen und Hits reset + // (kleine Toleranz, damit Fließkomma nicht nervt) + if (abs($target - $pending) > 0.5) { + $pending = $target; + $hits = 0; + $this->SetBuffer("CUR_{$ch}_PEND", (string)$pending); + $this->SetBuffer("CUR_{$ch}_HITS", (string)$hits); + // lastVal bleibt stehen bis raw "passt" + } + + // Sonderfall: target ~ 0 -> sofort auf 0 ziehen (optional) + if (abs($pending) < 0.5) { + $lastVal = 0.0; + $hits = 0; + $this->SetBuffer("CUR_{$ch}_VAL", (string)$lastVal); + $this->SetBuffer("CUR_{$ch}_HITS", (string)$hits); + return $lastVal; + } + + // Optional: Vorzeichen passend zum Ziel erzwingen (hilft bei “-2000, -3000, +3000, +4900”) + // Wenn Ziel positiv ist, ignoriere negative raw komplett (und umgekehrt) + if (($pending > 0 && $raw < 0) || ($pending < 0 && $raw > 0)) { + $hits = 0; + $this->SetBuffer("CUR_{$ch}_HITS", (string)$hits); + return $lastVal; + } + + // Prüfen ob raw im Fenster um pending liegt + if (abs($raw - $pending) <= $tolW) { + $hits++; + $this->SetBuffer("CUR_{$ch}_HITS", (string)$hits); + + // Erst nach N Treffern übernehmen (Debounce) + if ($hits >= $needHits) { + $lastVal = $raw; // oder: $pending, wenn du exakt das Ziel schreiben willst + $hits = 0; + $this->SetBuffer("CUR_{$ch}_VAL", (string)$lastVal); + $this->SetBuffer("CUR_{$ch}_HITS", (string)$hits); + } + } else { + // außerhalb -> Hits zurücksetzen + if ($hits !== 0) { + $hits = 0; + $this->SetBuffer("CUR_{$ch}_HITS", (string)$hits); + } + } + + return $lastVal; + }; + + + + + + $rawEV = (float)$aktEV; + $rawSDL = (float)$aktSDL; + + // Ziel = Sollwerte (das ist das, was du in deiner Beschreibung meinst) + $targetEV = (float)$pEvW; + $targetSDL = (float)$pSdlW; + + // Parameter: Toleranzband + Anzahl Treffer + // Beispiel: 300W Band, 2 Treffer (bei 2s Update => ~4s stabil) + $tolW = 300.0; + $needHits = 2; + + // Gefilterte Werte + $fEV = $filterCurrent("EV", $rawEV, $targetEV, $tolW, $needHits); + $fSDL = $filterCurrent("SDL", $rawSDL, $targetSDL, $tolW, $needHits); + + // Setzen (wichtig: SetIdentValue!) + $this->SetIdentValue("Aktuelle_Leistung_EV", (float)$fEV); + $this->SetIdentValue("Aktuelle_Leistung_SDL", (float)$fSDL); + + return $finalOutput;