Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor fixes on compare charts and updates #1972

Merged
merged 8 commits into from
Feb 7, 2025
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
17 changes: 14 additions & 3 deletions apps/predbat/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import os
from datetime import datetime, timedelta
from config import TIME_FORMAT, TIME_FORMAT_OCTOPUS
from utils import str2time, minutes_to_time, dp1, dp2
from utils import str2time, minutes_to_time, dp0, dp1, dp2
import yaml
import copy

Expand Down Expand Up @@ -188,8 +188,8 @@ def run_scenario(self, end_record):
"metric_keep10": dp2(metric_keep10),
"final_iboost": dp2(final_iboost),
"final_iboost10": dp2(final_iboost10),
"final_carbon_g": dp2(final_carbon_g),
"final_carbon_g10": dp2(final_carbon_g10),
"final_carbon_g": dp0(final_carbon_g),
"final_carbon_g10": dp0(final_carbon_g10),
"battery_value_start": dp2(battery_value_start),
"battery_value_end": dp2(battery_value_end),
"metric_real": dp2(metric_end),
Expand Down Expand Up @@ -320,6 +320,17 @@ def publish_data(self):
)
result["entity_id"] = entity_id

def publish_only(self):
"""
Update HA sensors only
"""
compare_list = self.pb.get_arg("compare_list", [])
if not compare_list:
return

self.select_best(compare_list, self.comparisons)
self.publish_data()

def run_all(self, debug=False, fetch_sensor=True):
"""
Compare a comparison in prices across multiple energy tariffs and report results
Expand Down
42 changes: 42 additions & 0 deletions apps/predbat/config/apps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,48 @@ pred_bat:
#futurerate_peak_premium_import: 14
#futurerate_peak_premium_export: 6.5

# Tariff comparison feature
# Adjust this list to the tariffs you want to compare, include your current tariff also
#compare_list:
# - id: 'current'
# name: 'Current Tariff'
# - id: 'igo_fixed'
# name: 'Intelligent GO import/Fixed export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/INTELLI-BB-VAR-23-03-01/electricity-tariffs/E-1R-INTELLI-BB-VAR-23-03-01-L/standard-unit-rates/'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/OUTGOING-VAR-BB-24-10-26/electricity-tariffs/E-1R-OUTGOING-VAR-BB-24-10-26-L/standard-unit-rates/'
# - id: 'igo_agile'
# name: 'Intelligent GO import/Agile export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/INTELLI-BB-VAR-23-03-01/electricity-tariffs/E-1R-INTELLI-BB-VAR-23-03-01-L/standard-unit-rates/'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/AGILE-OUTGOING-BB-23-02-28/electricity-tariffs/E-1R-AGILE-OUTGOING-BB-23-02-28-L/standard-unit-rates/'
# - id: 'go_fixed'
# name: 'GO import/Fixed export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/GO-VAR-BB-23-02-07/electricity-tariffs/E-1R-GO-VAR-BB-23-02-07-L/standard-unit-rates/'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/OUTGOING-VAR-BB-24-10-26/electricity-tariffs/E-1R-OUTGOING-VAR-BB-24-10-26-L/standard-unit-rates/'
# - id: 'go_agile'
# name: 'GO import/Agile export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/GO-VAR-BB-23-02-07/electricity-tariffs/E-1R-GO-VAR-BB-23-02-07-L/standard-unit-rates/'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/AGILE-OUTGOING-BB-23-02-28/electricity-tariffs/E-1R-AGILE-OUTGOING-BB-23-02-28-L/standard-unit-rates/'
# - id: 'agile_fixed'
# name: 'Agile import/Fixed export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/AGILE-24-10-01/electricity-tariffs/E-1R-AGILE-24-10-01-L/standard-unit-rates/'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/OUTGOING-VAR-BB-24-10-26/electricity-tariffs/E-1R-OUTGOING-VAR-BB-24-10-26-L/standard-unit-rates/'
# - id: 'agile_agile'
# name: 'Agile import/Agile export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/AGILE-24-10-01/electricity-tariffs/E-1R-AGILE-24-10-01-L/standard-unit-rates/'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/AGILE-OUTGOING-BB-23-02-28/electricity-tariffs/E-1R-AGILE-OUTGOING-BB-23-02-28-L/standard-unit-rates/'
# - id: 'flux'
# name: 'Flux import/Export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/FLUX-IMPORT-23-02-14/electricity-tariffs/E-1R-FLUX-IMPORT-23-02-14-L/standard-unit-rates'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/FLUX-EXPORT-BB-23-02-14/electricity-tariffs/E-1R-FLUX-EXPORT-BB-23-02-14-L/standard-unit-rates'
# - id: 'cosy_fixed'
# name: 'Cosy import/Fixed export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/COSY-22-12-08/electricity-tariffs/E-1R-COSY-22-12-08-L/standard-unit-rates'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/OUTGOING-VAR-BB-24-10-26/electricity-tariffs/E-1R-OUTGOING-VAR-BB-24-10-26-L/standard-unit-rates/'
# - id: 'cosy_agile'
# name: 'Cosy import/Agile export'
# rates_import_octopus_url: 'https://api.octopus.energy/v1/products/COSY-22-12-08/electricity-tariffs/E-1R-COSY-22-12-08-L/standard-unit-rates'
# rates_export_octopus_url: 'https://api.octopus.energy/v1/products/AGILE-OUTGOING-BB-23-02-28/electricity-tariffs/E-1R-AGILE-OUTGOING-BB-23-02-28-L/standard-unit-rates/'

# Alert feeds - customise to your country and the alert types, severity and keep value
#alerts:
# url: "https://feeds.meteoalarm.org/feeds/meteoalarm-legacy-atom-united-kingdom"
Expand Down
7 changes: 5 additions & 2 deletions apps/predbat/predbat.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,6 @@ def reset(self):
self.alerts = []
self.alert_active_keep = {}
self.alert_cache = {}

self.config_root = "./"
for root in CONFIG_ROOTS:
if os.path.exists(root):
Expand Down Expand Up @@ -767,10 +766,13 @@ def update_pred(self, scheduled=True):
self.expose_config("active", False)
self.save_current_config()

# Compare tariffs either when triggered or daily at midnight
if ((scheduled and self.minutes_now < RUN_EVERY) or self.compare_tariffs) and self.comparison:
# Compare tariffs either when triggered or daily at midnight
self.comparison.run_all()
self.compare_tariffs = False
else:
# Otherwise just update HA sensors to prevent then expiring
self.comparison.publish_only()

async def async_download_predbat_version(self, version):
"""
Expand Down Expand Up @@ -837,6 +839,7 @@ def initialize(self):

try:
self.reset()
self.update_time(print=False)
self.log("Starting HA interface")
try:
self.ha_interface = HAInterface(self)
Expand Down
46 changes: 37 additions & 9 deletions apps/predbat/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ def __init__(self, base) -> None:
self.compare_hist = {}
self.cost_yesterday_hist = {}
self.cost_yesterday_car_hist = {}
self.cost_yesterday_no_car = {}

def history_attribute(self, history, state_key="state", last_updated_key="last_updated", scale=1.0, attributes=False, print=False, daily=False, offset_days=0):
def history_attribute(self, history, state_key="state", last_updated_key="last_updated", scale=1.0, attributes=False, print=False, daily=False, offset_days=0, first=True):
results = {}
last_updated_time = None
last_day_stamp = None
Expand Down Expand Up @@ -78,7 +79,7 @@ def history_attribute(self, history, state_key="state", last_updated_key="last_u

day_stamp = last_updated_stamp.replace(hour=0, minute=0, second=0, microsecond=0)

if daily and day_stamp == last_day_stamp:
if first and daily and day_stamp == last_day_stamp:
continue
last_day_stamp = day_stamp

Expand All @@ -92,6 +93,18 @@ def history_attribute(self, history, state_key="state", last_updated_key="last_u

return results

def subtract_daily(self, hist1, hist2):
"""
Subtract the values in hist2 from hist1
"""
results = {}
for key in hist1:
if key in hist2:
results[key] = max(hist1[key] - hist2[key], 0)
else:
results[key] = hist1[key]
return results

def history_update(self):
"""
Update the history data
Expand All @@ -103,6 +116,7 @@ def history_update(self):
self.cost_hour_hist = self.history_attribute(self.base.get_history_wrapper(self.base.prefix + ".ppkwh_hour", 2))
self.cost_yesterday_hist = self.history_attribute(self.base.get_history_wrapper(self.base.prefix + ".cost_yesterday", 28), daily=True, offset_days=-1)
self.cost_yesterday_car_hist = self.history_attribute(self.base.get_history_wrapper(self.base.prefix + ".cost_yesterday_car", 28), daily=True, offset_days=-1)
self.cost_yesterday_no_car = self.subtract_daily(self.cost_yesterday_hist, self.cost_yesterday_car_hist)

compare_list = self.base.get_arg("compare_list", [])
for item in compare_list:
Expand All @@ -112,7 +126,7 @@ def history_update(self):
result = self.base.comparison.get_comparison(id)
if result:
self.compare_hist[id]["cost"] = self.history_attribute(self.base.get_history_wrapper(result["entity_id"], 28), daily=True)
self.compare_hist[id]["metric"] = self.history_attribute(self.base.get_history_wrapper(result["entity_id"], 2), state_key="metric", attributes=True, daily=True)
self.compare_hist[id]["metric"] = self.history_attribute(self.base.get_history_wrapper(result["entity_id"], 28), state_key="metric", attributes=True, daily=True)

async def start(self):
# Start the web server on port 5052
Expand Down Expand Up @@ -257,6 +271,9 @@ def get_header(self, title, refresh=0):
color: #4CAF50;
display: inline
}
p {
white-space: nowrap;
}
table {
border-collapse: collapse;
padding: 1px;
Expand Down Expand Up @@ -972,7 +989,7 @@ async def html_compare(self, request):
text += "</form>"

text += "<table>\n"
text += "<tr><th>ID</th><th>Name</th><th>Date</th><th>Metric</th><th>Cost</th><th>Cost 10%</th><th>Export</th><th>Import</th><th>Final SOC</th><th>Iboost</th><th>Carbon</th><th>Result</th>\n"
text += "<tr><th>ID</th><th>Name</th><th>Date</th><th>True cost</th><th>Cost</th><th>Cost 10%</th><th>Export</th><th>Import</th><th>Final SOC</th><th>Iboost</th><th>Carbon</th><th>Result</th>\n"

compare_list = self.base.get_arg("compare_list", [])

Expand All @@ -997,11 +1014,22 @@ async def html_compare(self, request):
best = result.get("best", False)
existing_tariff = result.get("existing_tariff", False)

selected = "<td bgcolor=#FFaaaa>Best<td>" if best else "<td>&nbsp;</td>"
try:
date_timestamp = datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
stamp = date_timestamp.strftime(TIME_FORMAT_DAILY)
except (ValueError, TypeError):
stamp = None

# Save current datapoint for today
if stamp and id in self.compare_hist:
self.compare_hist[id]["metric"][stamp] = metric
self.compare_hist[id]["cost"][stamp] = cost

selected = '<font style="background-color:#FFaaaa;>"> Best </font>' if best else ""
if existing_tariff:
selected += "<td bgcolor=#aaFFaa>Existing<td>"
selected += '<font style="background-color:#aaFFaa;"> Existing </font>'

text += "<tr><td><a href='#heading-{}'>{}</a></td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td>{}\n".format(
text += "<tr><td><a href='#heading-{}'>{}</a></td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td>\n".format(
id, id, name, date, metric, cost, cost10, export, imported, soc, final_iboost, final_carbon_g, selected
)

Expand All @@ -1014,8 +1042,8 @@ async def html_compare(self, request):
name = compare.get("name", "")
id = compare.get("id", "")
series_data.append({"name": name, "data": self.compare_hist.get(id, {}).get("metric", {}), "chart_type": "bar"})
series_data.append({"name": "Actual", "data": self.cost_yesterday_hist, "chart_type": "bar"})
series_data.append({"name": "Car actual", "data": self.cost_yesterday_car_hist, "chart_type": "bar"})
series_data.append({"name": "Actual", "data": self.cost_yesterday_hist, "chart_type": "line", "stroke_width": "2"})
series_data.append({"name": "Actual (no car)", "data": self.cost_yesterday_no_car, "chart_type": "line", "stroke_width": "2"})

now_str = self.base.now_utc.strftime(TIME_FORMAT)

Expand Down
8 changes: 5 additions & 3 deletions docs/compare.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ If you do not set an import or export rate for a particular tariff then your exi
# Tariff comparison feature
# Adjust this list to the tariffs you want to compare, include your current tariff also
compare_list:
- id: 'cap_none'
name: 'Price cap import/No export'
- id: 'current'
name: 'Current Tariff'
- id: 'cap_seg'
name: 'Price cap import/Seg export'
rates_import:
- rate 24.86
rates_export:
- rate 0
- rate 4.1
- id: 'igo_fixed'
name: 'Intelligent GO import/Fixed export'
rates_import_octopus_url: 'https://api.octopus.energy/v1/products/INTELLI-BB-VAR-23-03-01/electricity-tariffs/E-1R-INTELLI-BB-VAR-23-03-01-A/standard-unit-rates/'
Expand Down