diff --git a/apps/predbat/predbat.py b/apps/predbat/predbat.py index 894d6b0d7..4c4fa6f5a 100644 --- a/apps/predbat/predbat.py +++ b/apps/predbat/predbat.py @@ -366,6 +366,19 @@ "default": 0.0, }, {"name": "car_charging_hold", "friendly_name": "Car charging hold", "type": "switch", "default": True, "reset_inverter": True}, + {"name": "car_charging_manual_soc", "friendly_name": "Car charging manual SOC", "type": "switch", "default": False}, + { + "name": "car_charging_manual_soc_kwh", + "friendly_name": "Car manual SOC kWh", + "type": "input_number", + "min": 0, + "max": 100, + "step": 0.01, + "unit": "kWh", + "icon": "mdi:ev-station", + "enable": "car_charging_manual_soc", + "default": 0.0, + }, {"name": "octopus_intelligent_charging", "friendly_name": "Octopus Intelligent Charging", "type": "switch", "default": True}, { "name": "octopus_intelligent_ignore_unplugged", @@ -4030,6 +4043,9 @@ def run_prediction(self, charge_limit, charge_window, discharge_window, discharg final_soc = soc for car_n in range(0, self.num_cars): final_car_soc[car_n] = car_soc[car_n] + if minute == 0: + # Next car SOC + self.car_charging_soc_next[car_n] = car_soc[car_n] final_metric = metric final_import_kwh = import_kwh @@ -6461,6 +6477,7 @@ def reset(self): self.car_charging_battery_size = [100] self.car_charging_limit = [100] self.car_charging_soc = [0] + self.car_charging_soc_next = [None] self.car_charging_rate = [7.4] self.car_charging_loss = 1.0 self.discharge_window = [] @@ -6475,6 +6492,7 @@ def reset(self): self.charge_rate_now = 0 self.discharge_rate_now = 0 self.car_charging_hold = False + self.car_charging_manual_soc = False self.car_charging_threshold = 99 self.car_charging_energy = {} self.simulate_offset = 0 @@ -8000,6 +8018,7 @@ def get_car_charging_planned(self): self.car_charging_planned_response = self.get_arg("car_charging_planned_response", ["yes", "on", "enable", "true"]) self.car_charging_now_response = self.get_arg("car_charging_now_response", ["yes", "on", "enable", "true"]) + self.car_charging_from_battery = self.get_arg("car_charging_from_battery") # Car charging planned sensor for car_n in range(0, self.num_cars): @@ -8032,7 +8051,6 @@ def get_car_charging_planned(self): self.car_charging_rate[car_n] = float(self.get_arg("car_charging_rate")) self.car_charging_limit[car_n] = (float(self.get_arg("car_charging_limit", 100.0, index=car_n)) * self.car_charging_battery_size[car_n]) / 100.0 - self.car_charging_from_battery = self.get_arg("car_charging_from_battery") if self.num_cars > 0: self.log( "Cars {} charging from battery {} planned {}, charging_now {} smart {}, plan_time {}, battery size {}, limit {}, rate {}".format( @@ -9269,10 +9287,14 @@ def fetch_sensor_data(self): # Disable octopus charging if we don't have the slot sensor self.octopus_intelligent_charging = False - # Work out car SOC + # Work out car SOC and reset next self.car_charging_soc = [0.0 for car_n in range(0, self.num_cars)] + self.car_charging_soc_next = [None for car_n in range(0, self.num_cars)] for car_n in range(0, self.num_cars): - self.car_charging_soc[car_n] = (self.get_arg("car_charging_soc", 0.0, index=car_n) * self.car_charging_battery_size[car_n]) / 100.0 + if (car_n == 0) and self.car_charging_manual_soc: + self.car_charging_soc[car_n] = self.get_arg("car_charging_manual_soc_kwh") + else: + self.car_charging_soc[car_n] = (self.get_arg("car_charging_soc", 0.0, index=car_n) * self.car_charging_battery_size[car_n]) / 100.0 if self.num_cars: self.log("Current Car SOC kWh: {}".format(self.car_charging_soc)) @@ -9762,6 +9784,7 @@ def fetch_config_options(self): # Car options self.car_charging_hold = self.get_arg("car_charging_hold") + self.car_charging_manual_soc = self.get_arg("car_charging_manual_soc") self.car_charging_threshold = float(self.get_arg("car_charging_threshold")) / 60.0 self.car_charging_energy_scale = self.get_arg("car_charging_energy_scale") @@ -9847,6 +9870,14 @@ def update_pred(self, scheduled=True): self.expose_config("iboost_today", self.iboost_next) self.log("IBoost model today updated to {}".format(self.iboost_next)) + # Car SOC increment + if scheduled: + for car_n in range(0, self.num_cars): + if (car_n == 0) and self.car_charging_manual_soc: + self.log("Car charging Manual SOC current is {} next is {}".format(self.car_charging_soc[car_n], self.car_charging_soc_next[car_n])) + if self.car_charging_soc_next[car_n] is not None: + self.expose_config("car_charging_manual_soc_kwh", self.car_charging_soc_next[car_n]) + # Holiday days left countdown, subtract a day at midnight every day if scheduled and self.holiday_days_left > 0: if self.minutes_now < RUN_EVERY: diff --git a/docs/customisation.md b/docs/customisation.md index 8e6918a9e..dc8574f01 100644 --- a/docs/customisation.md +++ b/docs/customisation.md @@ -154,6 +154,11 @@ If Octopus Intelligent Charging is enabled the switch **'switch.predbat_octopus_ can be used to prevent Predbat from assuming the car will be charging when the car is unplugged. This will only work correctly if **car_charging_planned** is set correctly in apps.yaml to detect your car being plugged in. +If your car does not have an SOC sensor and you are not using Octopus Intelligent you can set **switch.predbat_car_charging_manual_soc** +to have Predbat create **input_number.predbat_car_charging_manual_soc_kwh** which will hold the cars current state of charge (soc) +in kWh. You will need to manually set this to the cars current charge level before charging, Predbat will increment it during +charging sessions but will not reset it automatically. + ## Calculation options See the Predbat mode setting as above for basic calculation options