Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions apps/predbat/predbat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 = []
Expand All @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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))

Expand Down Expand Up @@ -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")

Expand Down Expand Up @@ -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:
Expand Down
5 changes: 5 additions & 0 deletions docs/customisation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down