diff --git a/simpleAPI/simpleAPI_mqtt.py b/simpleAPI/simpleAPI_mqtt.py index 580c09dfc5..5a27b301e0 100755 --- a/simpleAPI/simpleAPI_mqtt.py +++ b/simpleAPI/simpleAPI_mqtt.py @@ -567,6 +567,10 @@ def _handle_write_operation(self, topic: str, payload: str): success = self._handle_bat_mode_operation(payload) if success: self._clear_set_topic(topic) + elif operation == 'bat_power_reserve': + success = self._handle_bat_power_reserve_operation(payload) + if success: + self._clear_set_topic(topic) else: log.error(f"Unknown operation: {operation}") @@ -760,6 +764,30 @@ def _handle_bat_mode_operation(self, payload: str) -> bool: log.info(f"Set bat_mode to {payload}") return True + def _handle_bat_power_reserve_operation(self, payload: str) -> bool: + """Handle battery power reserve operation. + + Sets the power (in Watts) that openWB reserves for the battery + during PV surplus charging, before releasing surplus to EV charging. + Value 0 = no reservation (equivalent to ev_mode behaviour). + Allows external energy managers to do proportional battery/EV sharing + without switching bat_mode. + """ + try: + watts = int(payload) + except ValueError: + log.error(f"Invalid bat_power_reserve value: {payload!r}. Must be an integer (Watts).") + return False + + if watts < 0: + log.error(f"Invalid bat_power_reserve value: {watts}. Must be >= 0.") + return False + + target_topic = "openWB/set/general/chargemode_config/pv_charging/bat_power_reserve" + self.client.publish(target_topic, watts, qos=0, retain=True) + log.info(f"Set bat_power_reserve to {watts}W") + return True + def _handle_instant_charging_limit_operation(self, payload: str) -> bool: """Handle instant charging limit type operation.""" valid_limits = ['none', 'soc', 'amount'] diff --git a/simpleAPI/src/ParameterHandler.php b/simpleAPI/src/ParameterHandler.php index f07af4f9bd..d01b330cf4 100644 --- a/simpleAPI/src/ParameterHandler.php +++ b/simpleAPI/src/ParameterHandler.php @@ -229,6 +229,8 @@ public function writeParameter($param, $value, $chargepointId = null) return $this->setChargepointLock($chargepointId, $value); case 'bat_mode': return $this->setBatMode($value); + case 'bat_power_reserve': + return $this->setBatPowerReserve($value); case 'instant_charging_limit': return $this->setInstantChargingLimit($chargepointId, $value); case 'instant_charging_amount': @@ -1534,6 +1536,36 @@ private function setBatMode($value) } } + /** + * Reservierte Batterie-Ladeleistung setzen (W) + * Setzt openWB/set/general/chargemode_config/pv_charging/bat_power_reserve + * Ermöglicht externes Energiemanagement der Speicherreservierung ohne UI-Eingriff. + */ + private function setBatPowerReserve($value) + { + $watts = intval($value); + + if ($watts < 0) { + return ['success' => false, 'message' => 'bat_power_reserve must be >= 0']; + } + + try { + $topic = "openWB/set/general/chargemode_config/pv_charging/bat_power_reserve"; + + if ($this->mqttClient->setValue($topic, $watts)) { + return [ + 'success' => true, + 'message' => "bat_power_reserve set to {$watts}W", + 'data' => ['bat_power_reserve' => $watts] + ]; + } + + return ['success' => false, 'message' => 'Failed to set bat_power_reserve']; + } catch (Exception $e) { + return ['success' => false, 'message' => 'Error setting bat_power_reserve: ' . $e->getMessage()]; + } + } + /** * Lese openWB/system/lastlivevaluesJson Topic 1:1 aus */