Skip to content

Commit

Permalink
Merge pull request #143 from fboundy/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
fboundy authored Feb 28, 2024
2 parents ba32cc0 + f3eef4b commit d59befe
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# PV Opt: Home Assistant Solar/Battery Optimiser v3.9.4
# PV Opt: Home Assistant Solar/Battery Optimiser v3.9.5

Solar / Battery Charging Optimisation for Home Assistant. This appDaemon application attempts to optimise charging and discharging of a home solar/battery system to minimise cost electricity cost on a daily basis using freely available solar forecast data from SolCast. This is particularly beneficial for Octopus Agile but is also benefeficial for other time-of-use tariffs such as Octopus Flux or simple Economy 7.

Expand Down
22 changes: 15 additions & 7 deletions apps/pv_opt/pv_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

USE_TARIFF = True

VERSION = "3.9.4"
VERSION = "3.9.5"
DEBUG = False

DATE_TIME_FORMAT_LONG = "%Y-%m-%d %H:%M:%S%z"
Expand Down Expand Up @@ -582,6 +582,10 @@ def _load_contract(self):

i = 0
n = 5

old_contract = self.contract
self.contract = None

while self.contract is None and i < n:
if self.get_config("octopus_auto"):
try:
Expand Down Expand Up @@ -727,7 +731,11 @@ def _load_contract(self):
if self.contract is None:
e = f"Failed to load contract in {n} attempts. FATAL ERROR"
self.rlog(e)
raise ValueError(e)
if old_contract is None:
raise ValueError(e)
else:
self.log("Reverting to previous contract", level="ERROR")
self.contract = old_contract

else:
if self.contract.tariffs["export"] is None:
Expand Down Expand Up @@ -1400,7 +1408,7 @@ def optimise(self):
self.static = pd.concat([solcast, consumption], axis=1)
self.time_now = pd.Timestamp.utcnow()

self.static = self.static[self.time_now.floor("30T") :].fillna(0)
self.static = self.static[self.time_now.floor("30min") :].fillna(0)
# self.load_consumption()
self.soc_now = self.get_config("id_battery_soc")
x = self.hass2df(self.config["id_battery_soc"], days=1, log=self.debug)
Expand Down Expand Up @@ -1967,7 +1975,7 @@ def _write_output(self):

for offset in [1, 4, 8, 12]:
loc = pd.Timestamp.now(tz="UTC") + pd.Timedelta(offset, "hours")
locs = [loc.floor("30T"), loc.ceil("30T")]
locs = [loc.floor("30min"), loc.ceil("30min")]
socs = [self.opt.loc[l]["soc"] for l in locs]
soc = (loc - locs[0]) / (locs[1] - locs[0]) * (socs[1] - socs[0]) + socs[0]
entity_id = f"sensor.{self.prefix}_soc_h{offset}"
Expand Down Expand Up @@ -2032,7 +2040,7 @@ def _get_hass_power_from_daily_kwh(
df.index = pd.to_datetime(df.index)
df = pd.to_numeric(df, errors="coerce")
df = (
df.diff(-1).fillna(0).clip(upper=0).cumsum().resample("30T")
df.diff(-1).fillna(0).clip(upper=0).cumsum().resample("30min")
).ffill().fillna(0).diff(-1) * 2000
df = df.fillna(0)
if start is not None:
Expand Down Expand Up @@ -2168,7 +2176,7 @@ def _compare_tariffs(self):
initial_soc = (
self.hass2df(self.config["id_battery_soc"], days=2, log=self.debug)
.astype(float)
.resample("30T")
.resample("30min")
.mean()
).loc[start]

Expand Down Expand Up @@ -2255,7 +2263,7 @@ def _get_solar(self, start, end):
)

days = (pd.Timestamp.now(tz="UTC") - start).days + 1
df = self.hass2df(entity_id, days=days).astype(float).resample("30T").ffill()
df = self.hass2df(entity_id, days=days).astype(float).resample("30min").ffill()
if df is not None:
df.index = pd.to_datetime(df.index)
df = -df.loc[dt[0] : dt[-1]].diff(-1).clip(upper=0).iloc[:-1] * 2000
Expand Down

0 comments on commit d59befe

Please sign in to comment.