diff --git a/.cspell/custom-dictionary-workspace.txt b/.cspell/custom-dictionary-workspace.txt
index 0741f05d8..2a7b451f4 100644
--- a/.cspell/custom-dictionary-workspace.txt
+++ b/.cspell/custom-dictionary-workspace.txt
@@ -306,6 +306,7 @@ startminute
startt
stdlib
stepline
+strptime
sunsynk
syscmd
tabindex
diff --git a/apps/predbat/alertfeed.py b/apps/predbat/alertfeed.py
index 6405064cf..25366ae64 100644
--- a/apps/predbat/alertfeed.py
+++ b/apps/predbat/alertfeed.py
@@ -65,7 +65,7 @@ def process_alerts(self, minutes_now, midnight_utc, testing=False):
if not alert_config:
return alerts, alert_active_keep
if not isinstance(alert_config, dict):
- self.log("Warn: AlertFeed: Alerts must be a dictionary, ignoring")
+ self.log("Warn: AlertFeed: Weather alerts must be a dictionary, ignoring")
return alerts, alert_active_keep
# Try apps.yaml
@@ -80,10 +80,10 @@ def process_alerts(self, minutes_now, midnight_utc, testing=False):
# If latitude and longitude are not found, we cannot process alerts
if latitude and longitude:
- self.log("AlertFeed: Processing alerts for approx position latitude {} longitude {}".format(dp1(latitude), dp1(longitude)))
+ self.log("AlertFeed: Processing weather alerts for approx position latitude {}, longitude {}".format(dp1(latitude), dp1(longitude)))
else:
if not testing:
- self.log("Warn: AlertFeed: No latitude or longitude found, cannot process alerts")
+ self.log("Warn: AlertFeed: No latitude or longitude found, cannot process weather alerts")
return alerts, alert_active_keep
area = alert_config.get("area", "")
@@ -121,7 +121,7 @@ def apply_alerts(self, alerts, keep, minutes_now, midnight_utc):
onset_minutes = int((onset - midnight_utc).total_seconds() / 60)
expires_minutes = int((expires - midnight_utc).total_seconds() / 60)
if expires_minutes >= minutes_now:
- self.log("Info: AlertFeed: Active alert: {} severity {} certainty {} urgency {} from {} to {} applying keep {}".format(alert.get("event"), severity, certainty, urgency, onset, expires, keep))
+ self.log("Info: AlertFeed: Active weather alert: {}, severity {}, certainty {}, urgency {} from {} to {}, applying battery keep {}%".format(alert.get("event"), severity, certainty, urgency, onset, expires, keep))
for minute in range(onset_minutes, expires_minutes):
if minute not in alert_active_keep:
alert_active_keep[minute] = keep
@@ -226,7 +226,7 @@ def filter_alerts(self, alerts, area=None, event=None, severity=None, certainty=
async def download_alert_data(self, url):
"""
- Download octopus free session data directly from a URL
+ Download Weather Alert data directly from a URL
"""
# Check the cache first
now = datetime.now()
@@ -235,7 +235,7 @@ async def download_alert_data(self, url):
pdata = self.alert_cache[url]["data"]
age = now - stamp
if age.seconds < (30 * 60):
- self.log("AlertFeed: Return cached alert data for {} age {} minutes".format(url, dp1(age.seconds / 60)))
+ self.log("AlertFeed: Return cached weather alert data from URL {}, age {} minutes".format(url, dp1(age.seconds / 60)))
self.update_success_timestamp()
return pdata
@@ -245,11 +245,11 @@ async def download_alert_data(self, url):
async with session.get(url) as response:
status_code = response.status
if status_code not in [200, 201]:
- self.log("Warn: AlertFeed: Error downloading alert data from URL {}, code {}".format(url, status_code))
+ self.log("Warn: AlertFeed: Error downloading weather alert data from URL {}, error code {}".format(url, status_code))
return None
text = await response.text()
- self.log("AlertFeed: Downloaded alert data from {} size {} bytes".format(url, len(text)))
+ self.log("AlertFeed: Downloaded weather alert data from URL {}, size {} bytes".format(url, len(text)))
# Return new data
self.alert_cache[url] = {}
@@ -258,7 +258,7 @@ async def download_alert_data(self, url):
self.update_success_timestamp()
return text
except (aiohttp.ClientError, Exception) as e:
- self.log("Warn: AlertFeed: Exception downloading alert data from URL {}: {}".format(url, e))
+ self.log("Warn: AlertFeed: Exception downloading weather alert data from URL {}: {}".format(url, e))
return None
def parse_alert_data(self, xml):
@@ -272,7 +272,7 @@ def parse_alert_data(self, xml):
try:
root = etree.fromstring(xml)
except Exception as e:
- self.log("Warn: Failed to extract alerts from xml data exception: {}".format(e))
+ self.log("Warn: Failed to extract weather alerts from XML data exception: {}".format(e))
if root:
for entry in root:
diff --git a/apps/predbat/execute.py b/apps/predbat/execute.py
index 7ff256c7c..1f38df7bd 100644
--- a/apps/predbat/execute.py
+++ b/apps/predbat/execute.py
@@ -839,7 +839,7 @@ def publish_inverter_data(self):
self.prefix + ".pv_power",
state=dp3(self.pv_power / 1000.0),
attributes={
- "friendly_name": "Predicted PV Power",
+ "friendly_name": "Current PV Power",
"state_class": "measurement",
"unit_of_measurement": "kW",
"icon": "mdi:battery",
@@ -849,7 +849,7 @@ def publish_inverter_data(self):
self.prefix + ".grid_power",
state=dp3(self.grid_power / 1000.0),
attributes={
- "friendly_name": "Predicted Grid Power",
+ "friendly_name": "Current Grid Power",
"state_class": "measurement",
"unit_of_measurement": "kW",
"icon": "mdi:battery",
@@ -859,7 +859,7 @@ def publish_inverter_data(self):
self.prefix + ".load_power",
state=dp3(self.load_power / 1000.0),
attributes={
- "friendly_name": "Predicted Load Power",
+ "friendly_name": "Current Load Power",
"state_class": "measurement",
"unit_of_measurement": "kW",
"icon": "mdi:battery",
@@ -869,7 +869,7 @@ def publish_inverter_data(self):
self.prefix + ".battery_power",
state=dp3(self.battery_power / 1000.0),
attributes={
- "friendly_name": "Predicted Battery Power",
+ "friendly_name": "Current Battery Power",
"state_class": "measurement",
"unit_of_measurement": "kW",
"icon": "mdi:battery",
diff --git a/apps/predbat/inverter.py b/apps/predbat/inverter.py
index 6a29c0cae..5396f9443 100644
--- a/apps/predbat/inverter.py
+++ b/apps/predbat/inverter.py
@@ -15,7 +15,7 @@
from datetime import datetime, timedelta
from config import INVERTER_DEF, SOLAX_SOLIS_MODES_NEW, SOLAX_SOLIS_MODES
from const import MINUTE_WATT, TIME_FORMAT, TIME_FORMAT_OCTOPUS, INVERTER_TEST, TIME_FORMAT_SECONDS, INVERTER_MAX_RETRY, INVERTER_MAX_RETRY_REST
-from utils import calc_percent_limit, compute_window_minutes, dp0, dp2, dp3, dp4, time_string_to_stamp, minute_data, minute_data_state, window2minutes
+from utils import calc_percent_limit, compute_window_minutes, dp0, dp1, dp2, dp3, dp4, time_string_to_stamp, minute_data, minute_data_state, window2minutes
TIME_FORMAT_HMS = "%H:%M:%S"
@@ -752,7 +752,7 @@ def find_charge_curve(self, discharge):
if soc_kwh_sensor and charge_rate_sensor and battery_power_sensor and predbat_status_sensor:
battery_power_sensor = battery_power_sensor.replace("number.", "sensor.") # Workaround as old template had number.
- self.log("Find {} curve with sensors {}, {}, {} and {}".format(curve_type, soc_kwh_sensor, charge_rate_sensor, predbat_status_sensor, battery_power_sensor))
+ self.log("Looking for {} curve with sensors {}, {}, {} and {}".format(curve_type, soc_kwh_sensor, charge_rate_sensor, predbat_status_sensor, battery_power_sensor))
if soc_kwh_percent:
soc_kwh_data = self.base.get_history_wrapper(entity_id=soc_kwh_sensor, days=self.base.max_days_previous, required=False)
else:
@@ -830,7 +830,7 @@ def find_charge_curve(self, discharge):
for minute in battery_power:
battery_power[minute] = -battery_power[minute]
min_len = min(len(soc_kwh), len(charge_rate), len(predbat_status), len(battery_power))
- self.log("Find {} curve has {} days of data, max days {}".format(curve_type, min_len / 60 / 24.0, self.base.max_days_previous))
+ self.log("Looking for {} curve, have found {} days of history data, max days {}".format(curve_type, dp1(min_len / 60 / 24.0), self.base.max_days_previous))
soc_percent = {}
for minute in range(0, min_len):
@@ -998,13 +998,13 @@ def find_charge_curve(self, discharge):
self.log("Note: Found incomplete battery {} curve (no data points), maybe try again when you have more data.".format(curve_type))
else:
self.log(
- "Note: Cannot find battery {} curve (no final curve found for battery to {}), one of the required settings for {}, {}_rate, battery_power and predbat.status do not have history, check apps.yaml".format(
- curve_type, curve_label, soc_label, curve_type
+ "Note: Cannot find battery {} curve (no full rate {} curve found for battery to {}), one of the required settings for {}, {}_rate, battery_power and predbat.status do not have history, check apps.yaml".format(
+ curve_type, curve_type, curve_label, soc_label, curve_type
)
)
else:
self.log("Note: Cannot find battery {} curve (missing history), one of the required settings for {}, {}_rate, battery_power and predbat.status do not have history, check apps.yaml".format(curve_type, soc_label, curve_type))
- self.log("Note: Sensor with history data lengths: {} {}, {}_rate {}, battery_power {}, predbat_status {}".format(soc_label, len(soc_kwh), curve_type, len(charge_rate), len(battery_power), len(predbat_status)))
+ self.log("Note: Sensor history data lengths: {} {}, {}_rate {}, battery_power {}, predbat_status {}".format(soc_label, len(soc_kwh), curve_type, len(charge_rate), len(battery_power), len(predbat_status)))
else:
self.log("Note: Cannot find battery {} curve (settings missing), one of the required settings for {}, {}_rate and battery_power are missing from apps.yaml".format(curve_type, soc_label, curve_type))
return {}
diff --git a/apps/predbat/octopus.py b/apps/predbat/octopus.py
index 01a423671..3398ca7a5 100644
--- a/apps/predbat/octopus.py
+++ b/apps/predbat/octopus.py
@@ -2047,8 +2047,8 @@ def load_octopus_slots(self, octopus_slots, octopus_intelligent_consider_full):
new_slot["average"] = self.rate_import.get(start_minutes, self.rate_min)
if octopus_slot_low_rate and source != "bump-charge":
new_slot["average"] = self.rate_min # Assume price in min
- new_slot["cost"] = new_slot["average"] * kwh
- new_slot["soc"] = car_soc
+ new_slot["cost"] = dp2(new_slot["average"] * kwh)
+ new_slot["soc"] = dp2(car_soc)
new_slots.append(new_slot)
if end_minutes_original > end_minutes:
@@ -2060,7 +2060,7 @@ def load_octopus_slots(self, octopus_slots, octopus_intelligent_consider_full):
if octopus_slot_low_rate and source != "bump-charge":
new_slot["average"] = self.rate_min # Assume price in min
new_slot["cost"] = 0.0
- new_slot["soc"] = car_soc
+ new_slot["soc"] = dp2(car_soc)
new_slots.append(new_slot)
else:
@@ -2072,8 +2072,8 @@ def load_octopus_slots(self, octopus_slots, octopus_intelligent_consider_full):
new_slot["average"] = self.rate_import.get(start_minutes, self.rate_min)
if octopus_slot_low_rate and source != "bump-charge":
new_slot["average"] = self.rate_min # Assume price in min
- new_slot["cost"] = new_slot["average"] * kwh
- new_slot["soc"] = car_soc
+ new_slot["cost"] = dp2(new_slot["average"] * kwh)
+ new_slot["soc"] = dp2(car_soc)
new_slots.append(new_slot)
return new_slots
@@ -2136,7 +2136,7 @@ def rate_add_io_slots(self, rates, octopus_slots):
assumed_price = self.rate_import.get(start_minutes, self.rate_min)
self.log(
- "Octopus Intelligent slot at {}-{} assumed price {} amount {} kWh location {} source {} octopus_slot_low_rate {}".format(
+ "Octopus Intelligent slot at {}-{}, assumed price {}, amount {}, kWh location {}, source {}, octopus_slot_low_rate {}".format(
self.time_abs_str(start_minutes), self.time_abs_str(end_minutes), dp2(assumed_price), dp2(kwh), location, source, octopus_slot_low_rate
)
)
diff --git a/apps/predbat/tests/test_octopus_slots.py b/apps/predbat/tests/test_octopus_slots.py
index 3718fa789..9f6e190f7 100644
--- a/apps/predbat/tests/test_octopus_slots.py
+++ b/apps/predbat/tests/test_octopus_slots.py
@@ -152,7 +152,7 @@ def run_load_octopus_slots_tests(my_predbat):
]
loaded_slots = my_predbat.load_octopus_slots(sample_bad, False)
- expected_loaded = "[{'start': 870, 'end': 900, 'kwh': 1.29, 'average': 4, 'cost': 5.16, 'soc': 1.29}, {'start': 900, 'end': 930, 'kwh': 3.17, 'average': 4, 'cost': 12.68, 'soc': 4.46}, {'start': 930, 'end': 960, 'kwh': 3.18, 'average': 4, 'cost': 12.72, 'soc': 7.640000000000001}, {'start': 960, 'end': 990, 'kwh': 3.14, 'average': 4, 'cost': 12.56, 'soc': 10}, {'start': 990, 'end': 1050, 'kwh': 7.47, 'average': 4, 'cost': 29.88, 'soc': 10}, {'start': 1050, 'end': 1080, 'kwh': 3.0, 'average': 4, 'cost': 12.0, 'soc': 10}]"
+ expected_loaded = "[{'start': 870, 'end': 900, 'kwh': 1.29, 'average': 4, 'cost': 5.16, 'soc': 1.29}, {'start': 900, 'end': 930, 'kwh': 3.17, 'average': 4, 'cost': 12.68, 'soc': 4.46}, {'start': 930, 'end': 960, 'kwh': 3.18, 'average': 4, 'cost': 12.72, 'soc': 7.64}, {'start': 960, 'end': 990, 'kwh': 3.14, 'average': 4, 'cost': 12.56, 'soc': 10}, {'start': 990, 'end': 1050, 'kwh': 7.47, 'average': 4, 'cost': 29.88, 'soc': 10}, {'start': 1050, 'end': 1080, 'kwh': 3.0, 'average': 4, 'cost': 12.0, 'soc': 10}]"
if str(loaded_slots) != expected_loaded:
print("ERROR: Loaded slots should be {}\ngot {}".format(expected_loaded, loaded_slots))
failed = True
diff --git a/docs/apps-yaml.md b/docs/apps-yaml.md
index b1984f344..d9cdb77c0 100644
--- a/docs/apps-yaml.md
+++ b/docs/apps-yaml.md
@@ -1630,12 +1630,20 @@ as the slug-id (Home Assistant add-on identifier) is different between GivTCP v2
Some batteries tail off their charge rate at high SoC% or their discharge rate at low SoC%, and these optional configuration items enable you to model this tail-off in Predbat.
Note that the charge/discharge curves *only* affect the accuracy of the charging/discharging model Predbat applies in the forward battery plan,
-Predbat will still instruct the inverter to charge/discharge at full rate regardless of the charging curve.
+Predbat will still instruct the inverter to charge/discharge at full rate regardless of the charging curve so not having these curves only has an impact on plan accuracy.
If you know the battery charge or discharge curves (e.g. manufacturer info or your own testing) then you can manually configure this in `apps.yaml`,
or Predbat can calculate the curves based on historical inverter charging/discharging data in Home Assistant.
-If the battery has not recently been fully charged or fully discharged then Predbat will not be able to calculate the curves and you'll get a warning in the logfile.
+If the battery has not recently been fully charged or fully discharged *at a charge/discharge rate that is at least 95% of your maximum charge/discharge rate* then Predbat will not be able to calculate the curves and you'll get a warning in the logfile.
+For some inverters you may not be able to practically charge/discharge at full rates so you'll keep getting the curve warning every time Predbat starts. Simply create dummy curves to stop this warning, e.g:
+
+```yaml
+ battery_charge_power_curve:
+ 100 : 1.0
+ battery_discharge_power_curve:
+ 1 : 1.0
+```
- **battery_charge_power_curve** - This optional configuration item enables you to model in Predbat a tail-off in charging at high SoC%.
@@ -1830,23 +1838,11 @@ gaps in the curve above 20 will use 20 degrees, and gaps below 0 will use 0 degr
0: 0.00
```
-## Alert System
+## Weather Alert System
Predbat can take data directly from the Meteo-Alarm feed and use it to trigger keeping your battery charged so you have power in the event of a power cut.
-Please look at their web site for more details. The `apps.yaml` must be configured to select the URL for your country.
-
-The event severity and certainty are all regular expressions and can be set to one or multiple values using regular expression syntax.
-Any unset values are ignored.
-
-Your location (from Home Assistant) is used to filter alerts that apply only to your area. If this does not work or if you want to change the location,
-you can also set **latitude** and **longitude** in the alerts section of the `apps.yaml`.
-
-Events that match the given criteria will try to keep your battery at the percentage level specified by keep (default 100%) during the entire event period.
-This works by using a much stronger version of best_soc_keep but only for that time period.
-
-Your Predbat status will also have [Alert] in it during the alert time period and the triangle alert symbol will show on your HTML plan for the time period
-of the alert.
+Please look at the [Meteo Alarm](https://meteoalarm.org/) for more details. The `apps.yaml` must be configured to select the URL for your country and the events you want Predbat to retain your battery level for.``
```yaml
# Alert feeds - customise to your country, the alert types, severity and keep value
@@ -1859,6 +1855,21 @@ of the alert.
keep: 40
```
+The event severity and certainty are all regular expressions and can be set to one or multiple values using regular expression syntax. Any unset values are ignored.
+
+Your location (from Home Assistant) is used to filter alerts that apply only to your area. If this does not work or if you want to change the location,
+you can also set **latitude** and **longitude** in the alerts section of the `apps.yaml`.
+
+Events that match the given criteria will try to keep your battery at the percentage level specified by keep (default 100%) during the entire event period.
+This works by using a much stronger version of best_soc_keep but only for that time period.
+
+Your Predbat status will also have [Alert] in it during the alert time period and the triangle alert symbol will show on your HTML plan for the time period of the alert.
+
+Predbat records details of any weather alerts in the entity **sensor.predbat_alertfeed_status** which has a state value of the textual description of the alert. The entity has two attributes:
+
+- **keep** - set to the SoC keep percentage figure specified in `apps.yaml` (or the default 100) during the alert time period so can be used in an automation trigger if you want to take additional actions in Home Assistant
+- **alerts** - set to a list of dictionaries of details of any current or future alert events that match your alert criteria in `apps.yaml`. Each list entry contains event severity, certainty, urgency, area, time period, title, etc.
+

## Triggers
@@ -1965,7 +1976,7 @@ so only 15 minutes of load will be predicted for tomorrow 3pm.
and has to use Sunday's 3:30pm load for tomorrow's prediction.
- Ditto the predicted load for tomorrow's (Tuesday) 4:00pm slot comes from Sunday 4pm.
-As today rolls forward and Predbat keeps on updating the forward plan every 5 minutes the prediction will be updated with the correct previous_day history as and when it exists.
+As today rolls forward and Predbat keeps on updating the forward plan each time it runs, the prediction will be updated with the correct previous_day history as and when it exists.
It's recommended therefore that days_previous isn't set to 1, or if it is, that you understand the way this has to work and the consequences.
If you want to set days_previous to take an average of the house load over all the days of the last week it's suggested that it be set as:
diff --git a/docs/components.md b/docs/components.md
index c7536d6d0..4917b352c 100644
--- a/docs/components.md
+++ b/docs/components.md
@@ -1,4 +1,4 @@
-# Predbat Components Documentation
+# Predbat Components
This document provides a comprehensive overview of all Predbat components, their purposes, and configuration options.
@@ -44,7 +44,7 @@ Stores and manages all historical data for Predbat, including energy usage, sens
#### When to enable (db)
-- You want to retain data longer than Home Assistant keeps or you want to run Predbat without Home Assistant
+- You want to retain data longer than Home Assistant keeps or you want to run Predbat without Home Assistant. Under normal use you should not need to configure DB manager and the component will be disabled.
#### Configuration Options (db)
@@ -571,7 +571,7 @@ Monitors weather alert feeds (MeteoAlarm) for severe weather warnings that might
- Checks for alerts every 30 minutes
- Processes weather warnings for your area
-- Can be configured with custom alert URLs and filters
+- Can be configured with custom alert URLs and filters in `apps.yaml`
#### Configuration Options (alert_feed)
@@ -581,7 +581,7 @@ Monitors weather alert feeds (MeteoAlarm) for severe weather warnings that might
#### Configuration example
-See the main configuration documentation for more details
+See the [Weather Alert](apps-yaml.md#weather-alert-system) for more details
---
diff --git a/docs/customisation.md b/docs/customisation.md
index 48322d367..9a6a83fce 100644
--- a/docs/customisation.md
+++ b/docs/customisation.md
@@ -36,7 +36,7 @@ The mode that Predbat operates in will change the operation, this can be configu
- Control charge & discharge
If the **switch.predbat_set_read_only** is set to On then this prevents Predbat from making modifications to the inverter settings (regardless of the configuration).
-Predbat will continue making and updating its prediction plan every 5 minutes, but no inverter changes will be made.
+Predbat will continue making and updating its prediction plan every 10 minutes (by default), but no inverter changes will be made.
This is useful if you want to override what Predbat is planning to do (e.g. your own automation), or whilst you are learning how Predbat works before turning it on 'in anger'.
_NOTE: Changing the Predbat mode or the read-only switch will cause Predbat to reset the inverter settings to default, this will disable both charge and discharge, reset charge and discharge rates to full power and reset the reserve to the default setting_
@@ -79,10 +79,11 @@ It's recommended for new users to start without expert mode and then maybe turn
## Performance related
-By default Predbat controls the inverter every 5 minutes and updates the plan every 10 minutes.
+Predbat controls the inverter every 5 minutes it runs, and by default, updates and recalculates the plan every 10 minutes.
This can however use a lot of CPU power especially on more complex tariffs like Agile when run on lower power machines such as Raspberry PIs and some thin clients.
-You can tweak **input_number.predbat_calculate_plan_every** (_expert mode_) (default 10 minutes) to reduce the frequency of replanning while keeping the inverter control in the 5-minute slots. E.g. a value of 10 or 15 minutes should also give good results.
+You can tweak **input_number.predbat_calculate_plan_every** (_expert mode_) (default 10 minutes) to reduce the frequency of replanning while keeping the inverter control in the fixed 5-minute slots.
+E.g. a value of 10 or 15 minutes should also give good results.
If you have performance problems leave **switch.predbat_calculate_second_pass** (_expert mode_) turned Off as it's quite CPU intensive and provides very little improvement for most systems.
@@ -190,6 +191,10 @@ A value of 0.1 assumes that 1 in every 10 times we will get the Solcast 10% scen
Predbat estimates solar generation for each half-hour slot to be a pv_metric10_weight weighting of the Solcast 10% PV forecast to the Solcast Median forecast.
A value of 0.15 (the default) is recommended.
+**switch.predbat_metric_pv_calibration_enable** When turned On (the default), Predbat will use historical actual solar generation data to calibrate your PV production estimates on a slot duration (default 30 minute) basis.
+This can be useful to adjust for your systems real performance.
+Do not use if you are using the [Solcast integration and have turned on the integration's auto dampening](https://github.com/BJReplay/ha-solcast-solar?tab=readme-ov-file#dampening-configuration).
+
## Historical load data
The historical load data is taken from the load sensor as configured in `apps.yaml` with the days are selected using **days_previous**, and weighted using **days_previous_weight** in `apps.yaml`.
@@ -337,14 +342,10 @@ If you set this to a negative value then Predbat will assume unpublished export
A scale factor can be set with **input_number.predbat_metric_inday_adjust_damping** (_expert mode_) (default 0.95) to either scale up or down the impact of the in-day adjustment (lower numbers scale down its impact).
The in-day adjustment factor can be seen in **predbat.load_inday_adjustment** and charted with the [In-Day Adjustment chart](creating-charts.md).
-**switch.predbat_metric_pv_calibration_enable** When turned On, Predbat will use historical data to calibrate your PV production estimates on a slot duration (default 30 minute) basis based on actual generation data.
-This can be useful to adjust for your systems real performance.
-Default is On.
-
**input_number.predbat_carbon_metric** (_carbon enable_) When Carbon footprint tracking is turned On (**switch.predbat_carbon_enable**) (Off by default),
you can specify a cost per kg of CO2 used to weight the selection of plans. Values of around 10-200 will give varying outcomes to trade off cost vs carbon footprint of your system.
-_Note: Carbon footprint tracking can only be turned on if `apps.yaml` is configured to point to the correct CO2 cost sensor_
+_Note: Carbon footprint tracking can only be turned on if `apps.yaml` is configured to point to the correct [CO2 cost sensor](energy-rates.md#grid-carbon-intensity)_
## Notifications
@@ -352,7 +353,7 @@ Predbat can send mobile notifications for various events. You can control which
Set the list of [devices to notify](apps-yaml.md#notify_devices) in `apps.yaml`.
| Switch | Default | Controls |
-|--------|---------|----------|
+| ------- | ------- | -------- |
| **switch.predbat_set_status_notify** | On | Notifications when Predbat operational status changes (e.g. Idle, Charging, Exporting) |
| **switch.predbat_set_inverter_notify** | Off | Notifications when inverter settings are changed (e.g. charge/discharge rates, reserve levels, time windows) |
| **switch.predbat_set_event_notify** | On | Notifications for energy market events (e.g. Octopus Saving Sessions joined, Axle VPP events scheduled) |
@@ -598,27 +599,31 @@ In summary:
- For short holidays set holiday_days_left to the number of full days you are away, including today but excluding the return day
- For longer holidays set holiday_days_left to the number of days you are away plus another 7 days until the data catches back up
-## Manual control
+## Manual Control
In some cases, you may want to override Predbat's planned behaviour and make a decision yourself. One way to achieve this is to put Predbat into read-only mode using **switch.predbat_set_read_only**.
-When going to read-only mode the inverter will be put back to the default settings and you should then control it yourself using your inverter controls directly.
+When going to read-only mode the inverter will be put back to the default settings and you can then control it yourself using your inverter controls directly.
-A better alternative in some cases is to tell Predbat what you want it to do using the manual force feature.
+A better alternative in some cases is to tell Predbat what you want it to do in a particular time slot using the Manual Control feature.
+
+Note that none of the manual control commands override the [Predbat mode](#predbat-mode) you have selected.
+So if for example you want to force Predbat to charge then you need to be in either 'Control charge' or 'Control charge & discharge' mode, and if you want to force Predbat to export then you need to be in 'Control charge & discharge mode'.
You can force the battery to be charged within a single slot by using the **select.predbat_manual_charge** selector.
-Pick the day and time slot you wish to charge in (up to 48 hours in advance), and Predbat will change the plan to charge in the selected slot.
-You can select multiple slots by using the drop-down menu more than once.
-When Predbat updates the plan you will see the slots picked to be charging slots in the current value of this selector,
-and annotated in the [Predbat HTML plan](predbat-plan-card.md#displaying-the-predbat-plan) with an upside down 'F' symbol.
+Pick the day and time slot you wish to charge in (up to 48 hours in advance), and Predbat will change the plan to charge in the selected slot. You can select multiple slots by using the drop-down menu more than once.
-Selected slots will be shown in the in the list in square brackets and you can cancel a force slot by selecting the slot time again.
+Selected slots will be shown in the list in square brackets, and you can cancel a Manual Control slot by selecting the slot time again.
-When you use the manual override features you can select the day and time from the next 48 hours, the overrides will be removed once their time slot expires (they do not repeat).
+When you use the Manual Control features you can select the day and time from the next 48 hours, the overrides will be removed once their time slot expires (they do not repeat).
The **off** option at the bottom of the list will cancel all selected force charges.

+When Predbat updates the plan you will see the slots that have been manually picked to be charging slots annotated in the [Predbat HTML plan](predbat-plan-card.md#displaying-the-predbat-plan) with an upside down 'F' symbol.
+
+
+
If you use the selector from an automation you can combine multiple time slots together, with times in the format HH:MM.
Entering the slot day is optional from an automation, and if you do not enter a day then the next slot with the matching time will be chosen.
@@ -634,17 +639,21 @@ data:
22:00,22:30,23:00
```
-All the other **select.predbat_manual_XX** controls operate in the same way.
+All the other **select.predbat_manual_XX** controls operate in a similar way.
-The **select.predbat_manual_export** selector can be used to manually force an export within a slot in the same way as the manual force charge feature.
-The force export takes priority over force charging.
+_NOTE_: once you select a day/time slot from any of the **select.predbat_manual_XX** selectors the selected time slot is immediately marked on the drop-down and you can then make another change.
+Predbat still has to update the plan which it will be doing so in the background, and this can take a few minutes to run (depending on the speed and power of the device you are running Home Assistant on),
+so don't be surprised why the [Predbat plan](predbat-plan-card.md) doesn't change immediately - remember you can see the date/time the plan was last updated on the first row of the plan.
+
+_CAUTION: If you leave Predbat turned off for a long period of time then the override timeslots could end up repeating when you restart_
+
+The **select.predbat_manual_export** selector can be used to manually force Predbat to export within a slot. If you set a force export then this takes priority over force charging.
The **select.predbat_manual_demand** selector is used to force Predbat to demand mode for a slot, this implies no forced grid charging or exporting of the battery.
House load will be supplied from solar, or the battery if there is insufficient solar, or grid import if there is insufficient battery charge.
-This is described as 'ECO' Mode for GivEnergy inverters but other inverters use different terminology.
+This is described as 'Eco' Mode for GivEnergy inverters but other inverters use different terminology.
-The **select.predbat_manual_freeze_charge** selector is used to force Predbat to freeze charge during a slot, this implies the battery will not discharge and will
-hold at the current level. The grid may be used if solar is not enough to cover the load.
+The **select.predbat_manual_freeze_charge** selector is used to force Predbat to freeze charge during a slot, this implies the battery will not discharge and will hold at the current level. The grid may be used if solar is not enough to cover the load.
The **select.predbat_manual_freeze_export** selector is used to force Predbat to freeze export during a slot, this implies the battery will not charge but will still discharge for the house load. Any solar will be exported to the grid.
@@ -658,36 +667,28 @@ the rate selected will be that configured in **input_number.predbat_manual_expor
Similar to manual_import_rates, if this selector is used in an automation you can set the time and rate together by making a selection in the format HH:MM=rate e.g. 12:30=29.5
-The **select.predbat_manual_load_adjust** selector is used to make adjustments to the predicted load for a slot, the adjustment in kWh (which is added to the predicted load) will be that
-configured in **input_number.predbat_manual_load_value** which can be adjusted prior to making a selection (default 0.5kWh).
+The **select.predbat_manual_load_adjust** selector is used to make adjustments to the predicted load in kWh for a slot, the load adjustment amount will be that configured in **input_number.predbat_manual_load_value** (default 0.5kWh)
+which can be adjusted prior to making a selection.
+Predbat will add the adjustment amount to the kWh predicted load for those slots.
-If this selector is used in an automation you can set the time and rate together by making a selection in the format HH:MM:SS=adjustment e.g. 12:30:00=0.5
+If this selector is used in an automation you can set the time and kWh load adjustment amount together by making a selection in the format HH:MM=adjustment e.g. 12:30=0.5
-The **select.predbat_manual_soc** selector is used to set a target State of Charge (SoC) percentage by a specific time.
+The **select.predbat_manual_soc** selector is used to set a target State of Charge (SoC) percentage for a specific time.
This is useful when you know you need a certain battery level at a particular time, for example before peak rates start or when you expect higher than normal consumption.
+
The SoC target percentage will be that configured in **input_number.predbat_manual_soc_value** (default 100%) which can be adjusted prior to making a selection.
For example, if you want the battery to be at 100% by 05:30, select that time slot. Predbat will plan charging to ensure the battery reaches the target SOC by that time.
-If this selector is used in an automation you can set the time and SoC together by making a selection in the format HH:MM:SS=percentage e.g. 05:30:00=100
-
-The manual SoC target works in conjunction with the weather alert system - if both are active at the same time, the higher SoC target will be used.
-
-When you use the manual override features you can only select times in the next 48 hours, the overrides will be removed once their time slot expires (they do not repeat).
-_NOTE_: once you select a time slot from any of the **select.predbat_manual_XX** selectors the selected time slot is immediately marked on the drop-down and you can then make another change.
-Predbat still has to update the plan which it will be doing so in the background,
-and this can take a few minutes to run (depending on the speed and power of the PC you are running Home Assistant on) so don't be surprised why the
-[Predbat plan](predbat-plan-card.md) doesn't change immediately - remember you can see the date/time the plan was last updated on the first row of the plan.
+If this selector is used in an automation you can set the time and SoC together by making a selection in the format HH:MM=percentage e.g. 05:30=100
-_CAUTION: If you leave Predbat turned off for a long period of time then the override timeslots could end up repeating when you restart_
-
-
+The manual SoC target works in conjunction with the [weather alert system](apps-yaml.md#weather-alert-system) - if both are active at the same time, the higher SoC target will be used.
## Manual API
**select.predbat_manual_api** enables you to overwrite configuration entries normally set in `apps.yaml`, e.g. from an automation.
-This is described in detail in [Car Charging](manual-api.md) and is mentioned here just for completeness.
+This is described in detail in [Manual API](manual-api.md) and is mentioned here just for completeness.
## Debug
diff --git a/docs/energy-rates.md b/docs/energy-rates.md
index 68fec1d73..495fbc853 100644
--- a/docs/energy-rates.md
+++ b/docs/energy-rates.md
@@ -377,7 +377,7 @@ You can also override the import or export energy rates (regardless of whether t
Rate override is used to set the specific date and time period where your rates are different, e.g. an Octopus Power Up session (zero rate for an hour or two),
or the British Gas half-price electricity on Sundays.
-Unfortunately, there aren't any API's available to feed this information automatically into Predbat so you will have to define your own input controls and use the [Predbat manual API](manual-api.md#example-solution-to-over-ride-predicted-house-load),
+Unfortunately, there aren't any API's available to feed this information automatically into Predbat so you will have to define your own input controls and use the [Predbat Manual API](manual-api.md#example-solution-to-over-ride-predicted-house-load),
or edit `apps.yaml` manually to set the appropriate rate over-ride dates and times:
```yaml
diff --git a/docs/faq.md b/docs/faq.md
index 77962a3b7..59ec1340d 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -121,7 +121,7 @@ And this should prevent the issue
## The plan doesn't charge or discharge when I expect it to
-Predbat can only work on the information it's given, although it does run every 5 minutes when it re-evaluates the plan and adjusts if necessary.
+Predbat can only work on the information it's given, although it does run every 5 minutes to execute the plan, and updates and re-evaluates the plan every 10 minutes, adjusting if necessary.
The plan Predbat produces assumes that your average load and PV forecasts are accurate and Predbat will aim to give you the maximum return.
diff --git a/docs/images/predbat-release.png b/docs/images/predbat-release.png
new file mode 100644
index 000000000..c76f60eb1
Binary files /dev/null and b/docs/images/predbat-release.png differ
diff --git a/docs/install.md b/docs/install.md
index c4aefcef2..c60e5938f 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -315,7 +315,7 @@ set the switch **switch.predbat_set_read_only** to Off and Predbat will start co
## Updating Predbat
Note that any future updates to Predbat will not overwrite the `apps.yaml` configuration file that you have tailored to your setup.
-If new Predbat releases introduce new features to apps.yaml you may therefore need to manually copy across the new apps.yaml settings from the [Template apps.yaml](apps-yaml.md#templates).
+If new Predbat releases introduce new features to `apps.yaml` you may therefore need to manually copy across the new settings from the [Template apps.yaml](apps-yaml.md#templates).
## Update via Home Assistant
@@ -329,6 +329,10 @@ Click on the update and select Install:

+Note that clicking the 'Skip' button give an error about auto-update being enabled for Predbat and that the update cannot be skipped. This warning appears because of Predbat's built-in auto-update feature and can be safely ignored.
+If you wish to skip or ignore a Predbat update then you don't need to do anything; Predbat will not auto-update (despite what HA says) unless you turn on Predbat's auto-update (see below) or choose a version to install.
+Predbat will remain running on the current version until you choose to update.
+
## Predbat built-in update
**Recommended for manual selection of versions or automatic updates**
@@ -343,6 +347,23 @@ Alternatively, if you turn On **switch.predbat_auto_update**, Predbat will autom
Once Predbat has been installed and configured you should update Predbat to the latest version by selecting the latest version in the **select.predbat_update** selector,
or by turning on the **switch.predbat_auto_update** to auto-update Predbat.
+## Manually installing a Predbat release
+
+The Predbat version selector **select.predbat_update** contains the last 25 release of Predbat, but sometimes if Predbat has stopped working,
+or if you wish to downgrade to an older version that is not on the drop-down menu, then you can manually install a Predbat release.
+
+Go to [Predbat releases on GitHub](https://github.com/springfall2008/batpred/releases) and find the release you wish to install.
+
+From the Assets list, download the source code (zip) file:
+
+
+
+- Unzip the source code file you have downloaded
+- Navigate to the release sub folder, then `apps`, and finally the `predbat` sub-folder
+- Shutdown Predbat
+- Copy all the .py files from the `predbat` sub-folder into your Predbat application folder in Home Assistant and overwrite the existing .py files. If you are running the Predbat add-on then the destination folder will be `/addon_configs/6adb4f0d_predbat`
+- Restart Predbat
+
## Upgrading from AppDaemon to Predbat add-on
These steps assume you already have a working Predbat system and want to upgrade to using the Predbat add-on instead of using either the AppDaemon or the AppDaemon-predbat add-on.
diff --git a/docs/inverter-setup.md b/docs/inverter-setup.md
index b56d68a0f..ddd39f1bc 100644
--- a/docs/inverter-setup.md
+++ b/docs/inverter-setup.md
@@ -317,15 +317,15 @@ input_number.plenticore_max_discharge # this is how fast inverter has to charge
Min value: 0
Max value: 100
-input_number.predbat_charge_limit # this can be used if charge limit is set to true
+input_number.predbat_charge_limit # this is the limit % Predbat is charging the battery to, can be used if charge limit is set to true
Min value: 0
Max value: 100
-input_number.predbat_reserve # this is used to set Min_soc in inverter
+input_number.predbat_reserve # this is used to set Min_soc in inverter, the minimum level to discharge the battery to
Min value: 0
Max value: 100
-input_number.predbat_charge_rate # This can be used to if low power charge mode is Enabled, remember to switch from "write -100 charging" to "write power rate charging" in automation
+input_number.predbat_charge_rate # This is the rate Predbat is charging the battery at, can be used if low power charge mode is Enabled, remember to switch from "write -100 charging" to "write power rate charging" in automation
Min value: 0
Max value: (Inverter Battery max charge in watt)
@@ -407,10 +407,10 @@ actions:
hub: kostalplenticore
value: >
[ {{ '0x%x' %
- unpack(pack(states('input_number.plenticore_g3_max_charge')
+ unpack(pack(states('input_number.plenticore_max_charge')
|float(0),
">f"), ">H", offset=2) | abs }}, {{ '0x%04x' %
- unpack(pack(states('input_number.plenticore_g3_max_charge')|float(0), ">f"), ">H")|abs }}
+ unpack(pack(states('input_number.plenticore_max_charge')|float(0), ">f"), ">H")|abs }}
]
enabled: true
- alias: Write power rate charging
@@ -1395,7 +1395,9 @@ max: 10
and Max sub-interval to '0:05:00'
- Create a helper entity of type 'Utility Meter', set the Name to 'Todays House Load', Input sensor to 'Todays House Load Integral' (that you just created) and Meter Reset Cycle to 'Daily'
-- When you first start Predbat, check the [Predbat log](output-data.md#predbat-logfile) to confirm that the correct sensor names are identified by the regular expressions in `apps.yaml`. Any non-matching expressions should be investigated and resolved
+- If you are using the inverter in Backup mode then you will need to set **input_number.predbat_set_reserve_min** to no lower than 15% minimum SoC, other modes allow a lower minimum SoC of 10%. This is a Solax limitation.
+
+- When you first start Predbat, check the [Predbat log](output-data.md#predbat-logfile) to confirm that the correct sensor names are identified by the regular expressions in `apps.yaml`. Any non-matching expressions should be investigated and resolved.
Please see this ticket in Github for ongoing discussion:
diff --git a/docs/manual-api.md b/docs/manual-api.md
index 065d22a4a..47276f29b 100644
--- a/docs/manual-api.md
+++ b/docs/manual-api.md
@@ -1,26 +1,24 @@
-# Predbat automation API
+# Manual API
**CAUTION** This is an expert feature only, you can break Predbat if you set the wrong things here.
-While for most people Predbat will do what you want without any adjustments there are some special cases where users wish to write some more complex
-automations which override Predbat settings
+While for most people Predbat will do what you want without any adjustments there are some special cases where users wish to write some more complex automations which override Predbat settings.
-For settings inside Home Assistant e.g. switch.predbat_*, select.predbat_* and input_number.predbat_* you can already use an automation to change these values
+For settings inside Home Assistant e.g. switch.predbat_*, select.predbat_* and input_number.predbat_* you can already use an automation to change these values.
-For settings in apps.yaml it's very difficult or impossible to update them via an automation.
+For settings in `apps.yaml` it's very difficult or impossible to update them via an automation.
For this reason, there is a selector called **select.predbat_manual_api** which works a bit like the manual override ones but this can have new values added using the select API in Home Assistant.
The only function the selector itself serves is to store override commands, you can clear from the selector but you have to set them using a service call.
-Certain settings from apps.yaml may be overridden using this method.
+Certain settings in `apps.yaml` may be overridden using this method.
Each override is in a string format and works a bit like a web URL, setting the command and the values.
## Data retention
The data for overrides is kept inside the Home Assistant selector itself and so will survive a reboot. There is likely a limit to the size of this data so be sure to remove
-old overrides when you are done with them. Keep in mind it's easy to lose all of the overrides with the 'off' option so do not keep important data here only use it for short-term
-automations.
+old overrides when you are done with them. Keep in mind it's easy to lose all of the overrides with the 'off' option so do not keep important data here only use it for short-term automations.
## Supported command formats
@@ -44,7 +42,7 @@ Commands are disabled again by putting them in square brackets e.g:
Below is an example of setting a rate override, you can clear all overrides by calling 'off' or this specific one only by calling the same thing again but in square brackets []
-For the rates you can use **rates_export_override** or **rates_import_override** with all the same options as [apps.yaml](energy-rates.md#manually-over-riding-energy-rates) but in a URL type format:
+For the rates you can use **rates_export_override** or **rates_import_override** with all the [same rate override options as apps.yaml](energy-rates.md#manually-over-riding-energy-rates), but in a URL type format:
```text
rates_export_override?start=17:00:00&end=19:00:00&rate=0
@@ -74,7 +72,7 @@ off
### Supported overrides
-The following settings can be overridden with this method:
+The following `apps.yaml` settings can be overridden using predbat_manual_api:
- rates_export_override
- rates_import_override
@@ -96,10 +94,13 @@ The following settings can be overridden with this method:
## Example solution to over-ride predicted house load
-One common feedback is there is no mechanism in Predbat to alter the predicted house load, for example ignoring the effects of extra washing load in the past, or to take account of planned extra load such as cooking a big Sunday dinner.
+Prior to the addition of **select.predbat_manual_load_adjust** a common feedback was that there was no mechanism in Predbat to alter the predicted house load,
+for example ignoring the effects of extra washing load in the past, or to take account of planned extra load such as cooking a big Sunday dinner.
The Predbat manual API provides a mechanism to meet this need by setting an export (or import) rates override.
+Now that you can use the manual load adjust selector to overwrite predicted load this example solution is retained as a worked example of how you can use the manual API to overwrite `apps.yaml` settings.
+
1. Control variables
Create a date/time helper called predbat_override_date of type date, another called predbat_override_start_time of type time, and a third called predbat_override_end_time also of type time.
diff --git a/docs/output-data.md b/docs/output-data.md
index 66b705356..16cf4eb95 100644
--- a/docs/output-data.md
+++ b/docs/output-data.md
@@ -490,13 +490,13 @@ Add a card of type 'markdown' to your dashboard to display a simple dashboard of
```yaml
type: markdown
content: >-
- {% set dd = (as_timestamp(now()) - as_timestamp("2024-12-22 17:20:00")) | timestamp_custom("%j")| int %}
+ {% set dd = ((as_timestamp(now()) - as_timestamp("2024-12-22 17:20:00")/86400) | int %}
{% set tw = (states('predbat.inverter_register_writes') | int) %}
{{ dd }} days, total {{ tw }} inverter writes
- {{ states('sensor.predbat_daily_inverter_writes')|int }} writes today
+ {{ states('sensor.predbat_daily_inverter_writes')|int(0) }} writes today
- Average {{ (tw / dd ) | int }} writes per day
+ Average {{ (tw / dd ) | int(0) }} writes per day
```
You'll need to change the hard-coded timestamp "2024-12-12..." to the date/time you first started counting Predbat inverter writes from to get the number of days and average writes per day correct.
@@ -504,7 +504,9 @@ You'll need to change the hard-coded timestamp "2024-12-12..." to the date/time
## Car data
- binary_sensor.predbat_car_charging_slot - A binary sensor indicating when to charge your car (if car planning is enabled) - which can be used in an automation
-as described in [Predbat led car charging](car-charging.md#car-charging-planning)
+as described in [Predbat led car charging](car-charging.md#car-charging-planning).
+The *planned* attribute of the binary_sensor contains details of all planned car charging activity with start and end dates and times, kWh to charge and charging cost.
+Note that the start and ends are expressed in 'MM-DD HH:MM:SS" format, use the template sensor below if you want to convert these to full date format, e.g. to display on an Apex chart
- predbat.car_charging_start - The time that car charging is planned to start at, in HH:MM:SS format
- predbat.car_soc_best - Predicted charge level of your car in the best plan at the end of the plan using the proposed car charging SoC% and charge window. Can also be charted
- predbat.cost_today_car - Current cost in pence so far today of charging all cars, with attribute of the projected future car charging costs and slots
@@ -513,6 +515,26 @@ as described in [Predbat led car charging](car-charging.md#car-charging-planning
See [Example Automation to separate car charging costs](car-charging.md#example-separating-car-charging-costs-for-multiple-cars) if you have multiple EV's and want to separate predbat.cost_today_car into costs per car.
+Template sensor to convert Predbat car charging times to full HA date format such as for displaying on an Apex chart:
+
+```yaml
+- unique_id: "PredBat Car Charging Times"
+- sensor:
+ - name: "PredBat Car Charging Times"
+ state: "{{ now() }}"
+ attributes:
+ planned_times: >
+ {% set times = state_attr('binary_sensor.predbat_car_charging_slot','planned') %}
+ {% set ns = namespace(erg = []) %}
+ {% set delta = now().date().strftime("%Y") | int %}
+ {% for time in times %}
+ {% set x = strptime(time.start,"%m-%d %H:%M:%S").replace(year=delta) %}
+ {% set item = { "start": x | string } %}
+ {% set ns.erg = ns.erg + [item] %}
+ {% endfor %}
+ {{ ns.erg }}
+```
+
## iBoost Solar Diverter data
- binary_sensor.predbat_iboost_active - A binary sensor indicating when there is excess solar and the solar diverter (e.g. iBoost, Eddi or just plain immersion heater) should be active,
@@ -634,8 +656,13 @@ See [editing configuration files within Home Assistant](install.md#editing-confi
## Automated monitoring that Predbat and GivTCP are running OK
-With GivTCP and Predbat performing an important function, managing your battery charging and discharging to best reduce your electricity bills,
-you may find these automations useful to monitor that GivTCP and Predbat are running OK, and if not, to raise an alert on your mobile device running the Home Assistant Companion app.
+With Predbat performing an important function, managing your battery charging and discharging to best reduce your electricity bills,
+you may find these automations useful to monitor that everything is running OK, and if not, to try restarting the failing add-on, and raise an alert on your mobile device running the Home Assistant Companion app.
+
+Two monitors are provided, one for Predbat and one for GivTCP (for GivEnergy inverters). Both monitors are written on the basis that Predbat/GivTCP are running as add-on's within the Home Assistant Supervisor.
+If you are running Predbat within Docker then the automation won't work as written.
+
+The GivTCP monitor is for use with a GivEnergy inverter, if you have a different inverter type then you may be able to use the GivTCP monitor as a basis for developing a similar inverter-specific error detection automation for your inverter.
To create a new automation:
@@ -774,7 +801,7 @@ NB: If you are using GivTCP v2 rather than v3, replace the '533ea71a_givtcp' wit
This automation will raise an alert if Predbat's status turns to *Error* for more than 5 minutes.
-In normal operation, Predbat will automatically run and update its forecast every 5 minutes. If the automation detects that Predbat has not done this for 20 minutes,
+In normal operation, Predbat will automatically run and update its plan and forecast every 5 minutes. If the automation detects that Predbat has not done this for 20 minutes,
then an alert will be raised and the automation will restart the Predbat add-on to try to resolve a 'hung Predbat' issue.
In the same way for the GivTCP and Mosquitto add-ons above, the last trigger requires you to enable a binary sensor that detects that the Predbat/AppDaemon add-on is running.
diff --git a/docs/predheat.md b/docs/predheat.md
index b1ca6d205..1a922fabf 100644
--- a/docs/predheat.md
+++ b/docs/predheat.md
@@ -6,7 +6,7 @@ Further details can be found in the [Predheat YouTube video](https://youtu.be/_-
## Operation
-The app runs every 5 minutes and it will automatically update its prediction for the heating system for the next period, up to a maximum of 48 hours.
+The app runs every 5 minutes (by default) and will automatically update its prediction for the heating system for the next period, up to a maximum of 48 hours.
The inputs are as follows
@@ -42,9 +42,9 @@ Then add in the Home Assistant service and connect up your API key to obtain hou
### Apex Charts install
-Use HACS to install Apex Charts (Lovelace frontend add-on) -
+Use HACS to install Apex Charts:
-There is a template for the Predheat charts in: [example_chart_predheat.yaml_template](https://raw.githubusercontent.com/springfall2008/batpred/refs/heads/main/templates/example_chart_predheat.yaml_template)
+There is a template of [example_Predheat charts](https://raw.githubusercontent.com/springfall2008/batpred/refs/heads/main/templates/example_chart_predheat.yaml_template) you can use.
Create a new Apex chart for each chart in this template and copy the YAML code into the chart.
@@ -110,6 +110,8 @@ For energy rates, they will come from the Predbat configuration, ensure you have
Note you can also change the tables for **gas_efficiency**, **heat_pump_efficiency** and **delta_correction** in the Predheat configuration but the defaults should be fine to get going.
+Set **run_every** to how often you want Predheat to update its heat energy prediction. By default this is every 5 minutes.
+
Now comes the tricky part, we need to calculate the heat loss for your house:
What will help here is historical temperature data, find a time period in the last few weeks when your heating was turned off (for a few hours beforehand) and the house is cooling down.
diff --git a/docs/web-interface.md b/docs/web-interface.md
index 1fc307109..8aee16c52 100644
--- a/docs/web-interface.md
+++ b/docs/web-interface.md
@@ -110,6 +110,22 @@ The Compare View provides access to Predbat's [Compare Energy Tariff feature](co

+### Log View
+
+Predbat writes detailed logging, status and progress activity information to a logfile as it runs and so the Log view provides an easy way to see and download the Predbat logfile.
+
+
+
+By default the Log view opens in the Warnings tab which shows a filtered list of Warnings and Errors in the Predbat logfile.
+
+The Errors tab shows a filtered list of logfile Errors, and the All tab shows all entries in the Predbat logfile.
+
+Normal log messages are coloured Green, Warnings are Orange, and Errors in Red. The Logfile view shows newest entries at the top and auto-refreshes so as Predbat is executing the most recent logs will appear at the top and the log will scroll downwards.
+
+The Download tab gives the ability to download the logfile.
+
+Further details about the Predbat logfile and its location is [described in the output data document](output-data.md#predbat-logfile).
+
#### Config View
The Config view provides a way to see and change all of Predbat's configuration entities in Home Assistant. For each entity is displayed the name, entity type, the current entity value and Predbat's default value for that entity.
@@ -128,7 +144,7 @@ and full explanation of Predbat's control entities and what they do can be found
The Apps view allows you to look at your `apps.yaml` configuration and to modify the values within the web browser without having to edit the YAML file directly.
Click the edit button to change a value, when all the edits are complete hit save to save the `apps.yaml` and Predbat will automatically be restarted with the new configuration.
-
+
Predbat validates your `apps.yaml` every time it runs and if there are any configuration issues it displays a count of those errors and highlights the items in error in red:
@@ -136,12 +152,6 @@ Predbat validates your `apps.yaml` every time it runs and if there are any confi
Further details of the `apps.yaml` error can be found in the [Predbat Log](#log-view).
-### Browse View
-
-The Browse view gives a simple file system browser to enable you to view any of the configuration, output and code files in the directory that Predbat is installed in.
-
-You can navigate around subfolders and view files, but not make any changes using the Browse view.
-
### Components View
The Components View enables you see the current status of the different [Predbat Components](components.md) and the key configuration settings being used by those components.
@@ -153,25 +163,15 @@ You can restart individual Predbat components if required.
The editor view allows you to edit apps.yaml as text directly within the web interface. If you make a syntax error then the error will be highlighted and save
will be disabled pending a fix.
-
-
-### Log View
-
-Predbat writes detailed logging, status and progress activity information to a logfile as it runs and so the Log view provides an easy way to see and download the Predbat logfile.
+
-
-
-By default the Log view opens in the Warnings tab which shows a filtered list of Warnings and Errors in the Predbat logfile.
-
-The Errors tab shows a filtered list of logfile Errors, and the All tab shows all entries in the Predbat logfile.
-
-Normal log messages are coloured Green, Warnings are Orange, and Errors in Red. The Logfile view shows newest entries at the top and auto-refreshes so as Predbat is executing the most recent logs will appear at the top and the log will scroll downwards.
+### Browse View
-The Download tab gives the ability to download the logfile.
+The Browse view gives a simple file system browser to enable you to view any of the configuration, output and code files in the directory that Predbat is installed in.
-Further details about the Predbat logfile and its location is [described in the output data document](output-data.md#predbat-logfile).
+You can navigate around subfolders and view files, but not make any changes using the Browse view.
-## Docs View
+### Docs View
Provides a quick link to the [Predbat documentation](https://springfall2008.github.io/batpred/).
diff --git a/docs/what-does-predbat-do.md b/docs/what-does-predbat-do.md
index 0843ce3ad..fa32e8054 100644
--- a/docs/what-does-predbat-do.md
+++ b/docs/what-does-predbat-do.md
@@ -112,7 +112,7 @@ but is set to prevent discharging into the car (requires **switch.predbat_car_ch
- **Read-Only (Axle)** - Predbat is in [read-only mode for the duration of an Axle VPP export event](energy-rates.md#axle-vpp), and will automatically return to a normal execution mode at the end of the Axle event.
-- **[Alert]** will be appended to the Predbat status if an [Alert is active](apps-yaml.md#alert-system).
+- **[Alert]** will be appended to the Predbat status if an [Alert is active](apps-yaml.md#weather-alert-system).
- **Calibration** - The inverter is calibrating the batteries.
On GivEnergy systems the battery state of charge (SoC) level has to be calibrated by performing a full battery discharge and then a full charge
diff --git a/templates/ginlong_solis.yaml b/templates/ginlong_solis.yaml
index 0d57cc17e..a4cb07a0d 100644
--- a/templates/ginlong_solis.yaml
+++ b/templates/ginlong_solis.yaml
@@ -347,10 +347,6 @@ pred_bat:
#notify_devices:
# - mobile_app_treforsiphone12_2
- # Set the frequency in minutes that this plugin is run
- # recommend something that divides by 60 (5, 10 or 15) or you won't trigger at the start of energy price slots
- run_every: 5
-
# Battery scaling makes the battery smaller (e.g. 0.9) or bigger than its reported
# If you have an 80% DoD battery that falsely reports it's kwh then set it to 0.8 to report the real figures
battery_scaling: 1.0
diff --git a/templates/predheat.yaml b/templates/predheat.yaml
index 1b395d395..c5433d883 100644
--- a/templates/predheat.yaml
+++ b/templates/predheat.yaml
@@ -6,6 +6,10 @@ predbat:
# Days forward
forecast_days: 2
+ # Set the frequency in minutes that predheat runs
+ # recommend something that divides by 60 (5, 10 or 15) or you won't trigger at the start of energy price slots
+ run_every: 5
+
# Days previous is the number of days back to find historical load data
# Recommended is 7 to capture day of the week but 1 can also be used
# if you have more history you could use 7 and 14 (in a list) but the standard data in HA only lasts 10 days
diff --git a/templates/sigenergy_sigenstor.yaml b/templates/sigenergy_sigenstor.yaml
index 1c21635f7..61741431c 100644
--- a/templates/sigenergy_sigenstor.yaml
+++ b/templates/sigenergy_sigenstor.yaml
@@ -316,10 +316,6 @@ pred_bat:
#notify_devices:
# - mobile_app_treforsiphone12_2
- # Set the frequency in minutes that this plugin is run
- # recommend something that divides by 60 (5, 10 or 15) or you won't trigger at the start of energy price slots
- run_every: 5
-
# Battery scaling makes the battery smaller (e.g. 0.9) or bigger than its reported
# If you have an 80% DoD battery that falsely reports it's kwh then set it to 0.8 to report the real figures
battery_scaling: 1.0
diff --git a/templates/solar_assistant_growatt_spa.yaml b/templates/solar_assistant_growatt_spa.yaml
index 1f09b3829..88b3fb476 100644
--- a/templates/solar_assistant_growatt_spa.yaml
+++ b/templates/solar_assistant_growatt_spa.yaml
@@ -303,10 +303,6 @@ pred_bat:
#notify_devices:
# - mobile_app_treforsiphone12_2
- # Set the frequency in minutes that this plugin is run
- # recommend something that divides by 60 (5, 10 or 15) or you won't trigger at the start of energy price slots
- run_every: 5
-
# Battery scaling makes the battery smaller (e.g. 0.9) or bigger than its reported
# If you have an 80% DoD battery that falsely reports it's kwh then set it to 0.8 to report the real figures
battery_scaling: 1.0
diff --git a/templates/solar_assistant_growatt_sph.yaml b/templates/solar_assistant_growatt_sph.yaml
index 3294df2e8..fcf77b235 100644
--- a/templates/solar_assistant_growatt_sph.yaml
+++ b/templates/solar_assistant_growatt_sph.yaml
@@ -297,10 +297,6 @@ pred_bat:
#notify_devices:
# - mobile_app_treforsiphone12_2
- # Set the frequency in minutes that this plugin is run
- # recommend something that divides by 60 (5, 10 or 15) or you won't trigger at the start of energy price slots
- run_every: 5
-
# Battery scaling makes the battery smaller (e.g. 0.9) or bigger than its reported
# If you have an 80% DoD battery that falsely reports it's kwh then set it to 0.8 to report the real figures
battery_scaling: 1.0
diff --git a/templates/solaredge.yaml b/templates/solaredge.yaml
index 4fe28eca1..e1c2e651e 100644
--- a/templates/solaredge.yaml
+++ b/templates/solaredge.yaml
@@ -318,10 +318,6 @@ pred_bat:
#notify_devices:
# - mobile_app_treforsiphone12_2
- # Set the frequency in minutes that this plugin is run
- # recommend something that divides by 60 (5, 10 or 15) or you won't trigger at the start of energy price slots
- run_every: 5
-
# Battery scaling makes the battery smaller (e.g. 0.9) or bigger than its reported
# If you have an 80% DoD battery that falsely reports it's kwh then set it to 0.8 to report the real figures
battery_scaling: 1.0
diff --git a/templates/solax_sx4.yaml b/templates/solax_sx4.yaml
index 499b1894e..ae51a7658 100644
--- a/templates/solax_sx4.yaml
+++ b/templates/solax_sx4.yaml
@@ -374,10 +374,6 @@ pred_bat:
#notify_devices:
# - mobile_app_treforsiphone12_2
- # Set the frequency in minutes that this plugin is run
- # recommend something that divides by 60 (5, 10 or 15) or you won't trigger at the start of energy price slots
- run_every: 5
-
# Battery scaling makes the battery smaller (e.g. 0.9) or bigger than its reported
# If you have an 80% DoD battery that falsely reports it's kwh then set it to 0.8 to report the real figures
battery_scaling: 1.0
diff --git a/templates/tesla_powerwall.yaml b/templates/tesla_powerwall.yaml
index 0176156b5..6292f1903 100644
--- a/templates/tesla_powerwall.yaml
+++ b/templates/tesla_powerwall.yaml
@@ -88,12 +88,6 @@ pred_bat:
soc_max:
- "13.5" # ensure this matches your usable kWh
- # ---- Powerwall controls via Teslemetry (must be writable) ----
- allow_charge_from_grid:
- - switch.my_home_allow_charging_from_grid
- allow_export:
- - select.my_home_allow_export
-
# --- Predbat service hooks (Tesla / Teslemetry) ---
# These hooks are called when Predbat wants to change the current
# state of charge/discharge. They can tie-in to other HA entities.
@@ -348,10 +342,6 @@ pred_bat:
#notify_devices:
# - mobile_app_treforsiphone12_2
- # Set the frequency in minutes that this plugin is run
- # recommend something that divides by 60 (5, 10 or 15) or you won't trigger at the start of energy price slots
- run_every: 5
-
# Battery scaling makes the battery smaller (e.g. 0.9) or bigger than its reported
# If you have an 80% DoD battery that falsely reports it's kwh then set it to 0.8 to report the real figures
battery_scaling: 1.0