RegisterPropertyInteger('SourceSoC', 0); // State of Charge $this->RegisterPropertyInteger('SourcePowerProd', 0); // Power Production $this->RegisterPropertyInteger('SourceIsReady', 0); // Is Ready (Bool) $this->RegisterPropertyInteger('SourceIsRunning', 0); // Is Running (Bool) $this->RegisterPropertyInteger('SourceMinSoC', 0); // Min SoC $this->RegisterPropertyInteger('SourceMaxSoC', 0); // Max SoC // Das Ziel (zum Schreiben/Steuern der Hardware) $this->RegisterPropertyInteger('TargetControlVar', 0); // Haupt-RequestAction Ziel // --------------------------------------------------------------------- // 2. Interne Variablen erstellen // --------------------------------------------------------------------- // Die Steuerungsvariablen $this->RegisterVariableString('Strategy', 'Strategy', '', 10); $this->RegisterVariableInteger('PowerSetpoint', 'Power Setpoint', '', 20); // Damit man sie im WebFront/Konsole ändern kann $this->EnableAction('Strategy'); $this->EnableAction('PowerSetpoint'); // MQTT Schnittstelle (JSON Container) // Input: Hier schreibt der MQTT Client rein $this->RegisterVariableString('MQTT_Write_In', 'MQTT Write Command (Input)', '~TextBox', 30); $this->RegisterVariableString('MQTT_Read_In', 'MQTT Read Command (Input)', '~TextBox', 50); // Output: Hier schreibt das Modul die Antwort rein (MQTT liest das) $this->RegisterVariableString('MQTT_Write_Out', 'MQTT Write Response (Output)', '~TextBox', 40); $this->RegisterVariableString('MQTT_Read_Out', 'MQTT Read Response (Output)', '~TextBox', 60); // Aktionen für Inputs aktivieren, damit Ereignisse darauf schreiben können $this->EnableAction('MQTT_Write_In'); $this->EnableAction('MQTT_Read_In'); } public function ApplyChanges() { // Diese Zeile nicht löschen parent::ApplyChanges(); // --------------------------------------------------------------------- // 3. Nachrichten registrieren (Events) // --------------------------------------------------------------------- // Wir wollen sofort reagieren, wenn sich der externe SoC ändert $socID = $this->ReadPropertyInteger('SourceSoC'); if (IPS_VariableExists($socID)) { $this->RegisterMessage($socID, VM_UPDATE); } // Auch reagieren, wenn wir selbst Strategy oder Setpoint ändern $this->RegisterMessage($this->GetIDForIdent('Strategy'), VM_UPDATE); $this->RegisterMessage($this->GetIDForIdent('PowerSetpoint'), VM_UPDATE); } // Empfängt Events (z.B. Änderung des SoC oder der Strategie) public function MessageSink($TimeStamp, $SenderID, $Message, $Data) { if ($Message == VM_UPDATE) { $socID = $this->ReadPropertyInteger('SourceSoC'); $stratID = $this->GetIDForIdent('Strategy'); $setID = $this->GetIDForIdent('PowerSetpoint'); // Wenn sich eine der steuerungsrelevanten Variablen ändert, Logik ausführen if ($SenderID == $socID || $SenderID == $stratID || $SenderID == $setID) { $this->ExecuteControlLogic(); } } } // Wird ausgeführt, wenn man Variable schaltet (WebFront, Skript oder MQTT-Event) public function RequestAction($Ident, $Value) { switch ($Ident) { case 'Strategy': case 'PowerSetpoint': $this->SetValue($Ident, $Value); // Sofort Logik neu berechnen $this->ExecuteControlLogic(); break; case 'MQTT_Write_In': // Wert setzen (optional, zur Ansicht) $this->SetValue($Ident, $Value); // JSON verarbeiten $this->ProcessWriteCommand($Value); break; case 'MQTT_Read_In': // Wert setzen (optional) $this->SetValue($Ident, $Value); // Lesebefehl verarbeiten $this->ProcessReadCommand(); break; default: throw new Exception("Invalid Ident"); } } // ------------------------------------------------------------------------- // LOGIK: Batterie Steuern (Skript 1) // ------------------------------------------------------------------------- private function ExecuteControlLogic() { $targetID = $this->ReadPropertyInteger('TargetControlVar'); // Sicherheitscheck: Existiert das Ziel? if (!IPS_VariableExists($targetID)) return; // Interne Werte laden $strategy = $this->GetValue('Strategy'); $setpoint = $this->GetValue('PowerSetpoint'); // SoC von extern holen $socID = $this->ReadPropertyInteger('SourceSoC'); $soc = IPS_VariableExists($socID) ? GetValue($socID) : 0; // Fall 1: STRATEGY = "activate" if ($strategy == "activate") { // Im Original: SetValue($idReqAction, ($setpoint)); RequestAction($targetID, $setpoint); return; } // Fall 2: STRATEGY = "stop" if ($strategy == "stop") { RequestAction($targetID, 0); return; } // Fall 3: Alles andere // Bei genau 50 -> auf 0 setzen if ((int)$soc == 50) { RequestAction($targetID, 0); return; } // Mode abhängig vom SoC if ($soc < 50) { // Laden (Positiver Betrag 2500) RequestAction($targetID, abs(2500)); } else { // Entladen (Negativer Betrag -2500) RequestAction($targetID, -2500); } } // ------------------------------------------------------------------------- // LOGIK: Writebefehl + Antwort (Skript 2) // ------------------------------------------------------------------------- private function ProcessWriteCommand($jsonInput) { if ($jsonInput == "") return; $data = json_decode($jsonInput, true); if ($data === null) return; // 1. power_setpoint verarbeiten if (isset($data['power_setpoint'])) { $val = $data['power_setpoint']; // Begrenzen auf -6000 bis +6000 if ($val > 6000) { $val = 6000; } elseif ($val < -6000) { $val = -6000; } $this->SetValue('PowerSetpoint', $val); } // 2. strategy verarbeiten if (isset($data['strategy'])) { $this->SetValue('Strategy', $data['strategy']); } // 3. Nach dem Schreiben Logik sofort ausführen, damit Hardware reagiert $this->ExecuteControlLogic(); // 4. Antwort generieren (Werte wieder lesen) $output = [ 'power_setpoint' => $this->GetValue('PowerSetpoint'), 'strategy' => $this->GetValue('Strategy') ]; $jsonOut = json_encode($output, JSON_PRETTY_PRINT); // In die Output-Variable schreiben (MQTT liest diese) $this->SetValue('MQTT_Write_Out', $jsonOut); } // ------------------------------------------------------------------------- // LOGIK: Lesebefehl (Skript 3) // ------------------------------------------------------------------------- private function ProcessReadCommand() { // IDs aus Properties laden $idPowerProduction = $this->ReadPropertyInteger('SourcePowerProd'); $idIsReady = $this->ReadPropertyInteger('SourceIsReady'); $idIsRunning = $this->ReadPropertyInteger('SourceIsRunning'); $idStateOfCharge = $this->ReadPropertyInteger('SourceSoC'); $idMinSOC = $this->ReadPropertyInteger('SourceMinSoC'); $idMaxSOC = $this->ReadPropertyInteger('SourceMaxSoC'); // Hilfsfunktion: Wert holen oder 0/false wenn ID fehlt $safeGet = function($id) { return IPS_VariableExists($id) ? GetValue($id) : 0; }; // Daten zusammenstellen $data = [ // Achtung: Originalskript rechnete -1 * Wert 'power_production' => -1 * $safeGet($idPowerProduction), 'is_ready' => (bool)$safeGet($idIsReady), 'is_running' => (bool)$safeGet($idIsRunning), 'state_of_charge' => $safeGet($idStateOfCharge), 'min_soc' => $safeGet($idMinSOC), 'max_soc' => $safeGet($idMaxSOC) ]; $json = json_encode($data, JSON_PRETTY_PRINT); // In Antwort-Variable schreiben $this->SetValue('MQTT_Read_Out', $json); } } ?>