<?php
class Verbraucher_Sperrbar extends IPSModule
{
    private $timerID;

    public function Create()
    {
        parent::Create();

        // Verbraucherspezifische Properties
        $this->RegisterPropertyInteger("Leistung", 0); // Standardwert für Volllast
        $this->RegisterPropertyInteger("MaxSperrZeit", 4);
        $this->RegisterPropertyInteger("Zeit_Zwischen_Zustandswechseln", 1);
        $this->RegisterPropertyInteger("Schaltkontakt1", 0);
        $this->RegisterPropertyInteger("Interval", 5); // Recheninterval
        $this->RegisterPropertyInteger("Mindestsperrleistung", 100);


        // Verbraucherspezifische Variabeln
        $this->RegisterVariableInteger("DailyOnTime", "DailyOnTime", "", 0);
        $this->RegisterVariableBoolean("IsTimerActive", "IsTimerActive", "", 0);
        $this->RegisterVariableBoolean("IstNacht", "IstNacht", "", 0);
        $this->RegisterVariableInteger("Letzte_Sperrleistung", "Letzte_Sperrleistung", "", 0);

        
        // Verbraucherspezifischer Timer
        $this->SetValue("IsTimerActive", false);
        $this->RegisterTimer("ZustandswechselTimer",0,"IPS_RequestAction(" .$this->InstanceID .', "ResetTimer", "");');

        // Variabeln für Kommunkation mit Manager
        $this->RegisterVariableInteger("Sperre_Prio", "Sperre_Prio");
        $this->RegisterVariableInteger("PV_Prio", "PV_Prio");
        $this->RegisterVariableBoolean("Idle", "Idle", "", 0);
        $this->RegisterVariableInteger("Aktuelle_Leistung", "Aktuelle_Leistung", "", 0);
        $this->RegisterVariableFloat("Bezogene_Energie", "Bezogene_Energie", "", 0);
        $this->RegisterVariableString("PowerSteps", "PowerSteps");
        $this->RegisterVariableInteger("Power", "Power");
        $this->RegisterVariableBoolean("Is_Peak_Shaving", "Is_Peak_Shaving");
        $this->RegisterVariableInteger("Leistung_Delta", "Leistung_Delta", "", 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_Verb",$this->ReadPropertyInteger("Interval")*1000,"IPS_RequestAction(" .$this->InstanceID .', "Do_UserCalc", "");');

    }

    public function ApplyChanges()
    {
        parent::ApplyChanges();
        $this->SetTimerInterval("Timer_Do_UserCalc_Verb",$this->ReadPropertyInteger("Interval")*1000); 
    }

    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 "ResetTimer":
                $this->ResetTimer(); 
                break; 

            case "Do_UserCalc":
                $this->SetAktuelle_Leistung($this->GetValue("Power"));
                $this->GetCurrentData($this->GetValue("Is_Peak_Shaving"));
                break; 

            default:
                throw new Exception("Invalid Ident");
        }
    }

    // Methode zum Setzen der PowerSteps und Timer starten
    public function SetTimerOn()
    {
        // Timer setzen, der nach "Zeit_Zwischen_Zustandswechseln" abläuft
        $zeitZwischenZustandswechseln = $this->ReadPropertyInteger("Zeit_Zwischen_Zustandswechseln");

        if($zeitZwischenZustandswechseln>0){
            $this->SetTimerInterval("ZustandswechselTimer", $zeitZwischenZustandswechseln * 60000); // Timer in Millisekunden
            // Timer-Status auf true setzen
            $this->SetValue("IsTimerActive", true);
        }else{
            $this->SetValue("IsTimerActive", false);

        }
    }

    // Methode zum Zurücksetzen von PowerSteps nach Ablauf des Timers
    public function ResetTimer()
    {
        // Timer stoppen
        $this->SetTimerInterval("ZustandswechselTimer", 0);

        // Timer-Status auf false setzen
        $this->SetValue("IsTimerActive", false);
    }

    // Methode zum Setzen des aktuellen Stromverbrauchs
    public function SetAktuelle_Leistung(float $power)
    {
        // Hier eine Leistungsänderung detektieren für Idle und interne Mindestlaufzeiten
        $this->CheckIdle($power);
        if ($this->GetValue("Aktuelle_Leistung") != $power) {
            $this->SetTimerOn();
        }
        $this->SetValue("Aktuelle_Leistung", $power);

        // Verbrauchte Energie berechnen
        $this->SetValue("Bezogene_Energie", ($this->GetValue("Bezogene_Energie") + ($this->GetValue("Aktuelle_Leistung")*($this->ReadPropertyInteger("Interval")/3600))));

        $Leistung = GetValue($this->ReadPropertyInteger("Leistung"));
        $schaltkontaktID = $this->ReadPropertyInteger("Schaltkontakt1");


        if ($this->GetValue("Is_Peak_Shaving") == false) {
            $schaltkontaktStatus = false;
        } elseif($power==0 && ((GetValue($schaltkontaktID)==true)||($Leistung>=$this->ReadPropertyInteger("Mindestsperrleistung")))){
            $schaltkontaktStatus = true;
        }else{
            $schaltkontaktStatus = false;
        }

        // Schaltkontaktstatus ändern
        SetValue($this->ReadPropertyInteger("Schaltkontakt1"), $schaltkontaktStatus);

        if ($schaltkontaktStatus==true) {
            $this->SetValue("DailyOnTime", $this->GetValue("DailyOnTime") + 1);
        }
    }

    // Methode zum Abrufen der aktuellen Daten
    public function GetCurrentData(bool $Peak)
    {
        $IstNacht = $this->GetValue("IstNacht");
        $NeuesIstNacht = $this->ist_nachts();

        if ($IstNacht == false && $NeuesIstNacht == true) {
            $this->SetValue("DailyOnTime", 0);
        }

        $this->SetValue("IstNacht", $NeuesIstNacht);

        if(GetValue($this->ReadPropertyInteger("Leistung"))>=$this->ReadPropertyInteger("Mindestsperrleistung")){
            $this->SetValue("Letzte_Sperrleistung", GetValue($this->ReadPropertyInteger("Leistung"))) ;
        }

        // Überprüfen, ob der Timer aktiv ist
        if ($this->GetValue("IsTimerActive")) {
            // Timer ist aktiv, PowerSteps setzen
            $this->SetValue("PowerSteps", json_encode([$this->GetValue("Aktuelle_Leistung")]));
            return; 
        }

        $DailyOnTime = $this->GetValue("DailyOnTime");
        $maxlaufzeit = $this->ReadPropertyInteger("MaxSperrZeit") * 60 * 60 / $this->ReadPropertyInteger("Interval");

        if($Peak==false){
            $this->SetValue("PowerSteps",json_encode([0]));
        }        // Wenn Maxlaufzeit nicht erreicht ist
        elseif($DailyOnTime < $maxlaufzeit) {
            if((GetValue($this->ReadPropertyInteger("Leistung"))>=$this->ReadPropertyInteger("Mindestsperrleistung")) || GetValue($this->ReadPropertyInteger("Schaltkontakt1"))==true) {
                $this->SetValue("PowerSteps", json_encode([0, (int)$this->GetValue("Letzte_Sperrleistung")]));
            } else {
                $this->SetValue("PowerSteps",json_encode([0]));
            }
        }
        // Andernfalls
        else {
            $this->SetValue("PowerSteps",json_encode([$this->GetValue("Letzte_Sperrleistung")]));
        }

    }

    public function CheckIdle($power)
    {
        $lastpower = GetValue($this->GetIDForIdent("Aktuelle_Leistung"));
        if ($lastpower != $power) {
            $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 ist_nachts()
    {
        date_default_timezone_set("Europe/Berlin"); // Setze hier deine Zeitzone

        $aktuelle_zeit = strtotime(date("H:i")); // Aktuelle Zeit in Stunden und Minuten umwandeln
        $start_nacht = strtotime("24:00"); // Startzeit der Nacht (22 Uhr)
        $ende_nacht = strtotime("07:00"); // Endzeit der Nacht (7 Uhr)

        if ($aktuelle_zeit >= $start_nacht || $aktuelle_zeit < $ende_nacht) {
            return true;
        } else {
            return false;
        }
    }
}

?>
