Skip to content

Commit

Permalink
Added first iteration of Go capability
Browse files Browse the repository at this point in the history
  • Loading branch information
markgdev committed Jul 10, 2021
1 parent ae4b8ee commit f028530
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 60 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ octopusagile:
serial: 00000000
auth: abc00000000
startdate: "2020-05-08"
# Easily switch between agile and go rates.
# If you include gorate, it'll override
# the times for the times specified in gotimes
gorate: 5
# You can leave godayrate out to go by
# Agile rates outside of offpeak period
godayrate: 16.26
gotimes:
- "23:30:00"
- "00:00:00"
- "00:30:00"
- "01:00:00"
- "01:30:00"
- "02:00:00"
- "02:30:00"
- "03:00:00"
moneymakers:
- switch.water_heater: null
- climate.downstairs:
Expand Down
49 changes: 16 additions & 33 deletions custom_components/octopusagile/OctopusAgile/Agile.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def round_time(self, t):
minute = 30
return (t.replace(second=0, microsecond=0, minute=minute, hour=t.hour))

def __init__(self, area_code=None, auth=None, mpan=None, serial=None, gas=None):
def __init__(self, area_code=None, auth=None, mpan=None, serial=None, gas=None, gorate=None, godayrate=None, gotimes=[]):
self.base_url = 'https://api.octopus.energy/v1'
self.meter_points_url = f'{self.base_url}/electricity-meter-points/'
self.cost_url = f'{self.base_url}/products/AGILE-18-02-21/electricity-tariffs'
Expand All @@ -33,6 +33,10 @@ def __init__(self, area_code=None, auth=None, mpan=None, serial=None, gas=None):
self.MPAN = mpan
self.SERIAL = serial

self.gorate = gorate
self.godayrate = godayrate
self.gotimes = gotimes

if area_code is None:
self.area_code = self.find_region(self.MPAN)
else:
Expand Down Expand Up @@ -193,6 +197,17 @@ def get_raw_rates_json(self, date_from, date_to=None):
f'standard-unit-rates/{ date_from }{ date_to }', headers=headers)
# print(r)
results = r.json()
# go_times = ["17:00:00", "17:30:00"]
if self.gorate is not None:
for result in results["results"]:
is_go_time = any(gotime in result["valid_from"] for gotime in self.gotimes)
if is_go_time:
result["value_inc_vat"] = round(self.gorate, 2)
result["value_exc_vat"] = round(self.gorate/1.05,2)
elif self.godayrate is not None:
result["value_inc_vat"] = round(self.godayrate, 2)
result["value_exc_vat"] = round(self.godayrate/1.05,2)

_LOGGER.debug(r.url)
return results

Expand Down Expand Up @@ -335,38 +350,6 @@ def get_consumption(self, start, end):
consumption = requests.get(url=consumption_url_str, auth=(self.auth, ''))
return consumption.json()

def aggregate_consumption(self):
week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")

end = datetime.now().date()
start = end - timedelta(days=30)

data = self.get_consumption(start, end)
hourly = {}
daily = {}
hour_daily = {}

for record in data['results']:
start = dateutil.parser.parse(record['interval_start'])
if start.minute not in [0, 30]: continue

if f"{start.hour}:{start.minute:02}" not in hourly:
hourly[f"{start.hour}:{start.minute:02}"] = []
hourly[f"{start.hour}:{start.minute:02}"].append(record['consumption'])

if week_days[start.weekday()] not in daily:
daily[week_days[start.weekday()]] = []
daily[week_days[start.weekday()]].append(record['consumption'] * 48)

if f"{week_days[start.weekday()]} {start.hour}:{start.minute:02}" not in hour_daily:
hour_daily[f"{week_days[start.weekday()]} {start.hour}:{start.minute:02}"] = []
hour_daily[f"{week_days[start.weekday()]} {start.hour}:{start.minute:02}"].append(record['consumption'])

for d in [hourly, daily, hour_daily]:
for key, value in d.items():
d[key]=round(sum(value) / len(value), 3)
return hourly, daily, hour_daily

def calculcate_cost(self, start, end):
jconsumption = self.get_consumption(start, end)
jcost = self.get_raw_rates_json(f"{start.isoformat()}T00:00:00Z", f"{end.isoformat()}T23:59:59Z")
Expand Down
41 changes: 14 additions & 27 deletions custom_components/octopusagile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ def setup(hass, config):
auth = config["octopusagile"]["auth"]
mpan = config["octopusagile"]["mpan"]
serial = config["octopusagile"]["serial"]
myrates = Agile(area_code=region_code, auth=auth, mpan=mpan, serial=serial)
gorate = config["octopusagile"].get("gorate", None)
godayrate = config["octopusagile"].get("godayrate", None)
gotimes = config["octopusagile"].get("gotimes", [])
myrates = Agile(area_code=region_code, auth=auth, mpan=mpan, serial=serial, gorate=gorate, godayrate=godayrate, gotimes=gotimes)
hass.states.set(f"octopusagile.region_code", region_code)
startdate = config["octopusagile"]["startdate"]
hass.states.set(f"octopusagile.startdate", startdate)
Expand All @@ -79,12 +82,6 @@ def setup(hass, config):
device_times = data.get("device_times", {})
for entity_id, vals in device_times.items():
hass.states.set(f"octopusagile.{entity_id}", vals["start_time"], vals["attribs"])
avg_rate_inc_peak = data.get("avg_rate_inc_peak")
if avg_rate_inc_peak is not None:
hass.states.set(f"octopusagile.avg_rate_inc_peak", avg_rate_inc_peak, {"unit_of_measurement": "p/kWh"})
avg_rate_exc_peak = data.get("avg_rate_exc_peak")
if avg_rate_exc_peak is not None:
hass.states.set(f"octopusagile.avg_rate_exc_peak", avg_rate_exc_peak, {"unit_of_measurement": "p/kWh"})
f.close()
except IOError:
print(f"{datatorefile} does not exist")
Expand Down Expand Up @@ -210,15 +207,19 @@ def handle_update_timers(call):

hass.states.set(f"octopusagile.timers", "", {"timers":timer_list})


jsonstr = json.dumps({"timers":timer_list, "rates":new_rates, "all_rates": new_rates})
f = open(datatorefile,"w")
f.write(jsonstr)
f.close()

# Calc averages for the next day
# Including peak
date_from = datetime.strftime(datetime.utcnow(), '%Y-%m-%dT23:00:00Z')
date_to = datetime.strftime((datetime.utcnow() + timedelta(days=1)), f"%Y-%m-%dT23:00:00Z")
rates_exc_peak = myrates.get_rates(date_from, date_to)["date_rates"]
avg_rate_inc_peak = round(sum(rates_exc_peak.values())/len(rates_exc_peak.values()), 2)
hass.states.set(f"octopusagile.avg_rate_inc_peak", avg_rate_inc_peak, {"unit_of_measurement": "p/kWh"})
if len(rates_exc_peak.values()) > 0:
avg_rate_inc_peak = round(sum(rates_exc_peak.values())/len(rates_exc_peak.values()), 2)
hass.states.set(f"octopusagile.avg_rate_inc_peak", avg_rate_inc_peak)

# Excluding peak
date_from = datetime.strftime(datetime.utcnow(), '%Y-%m-%dT23:00:00Z')
Expand All @@ -229,19 +230,9 @@ def handle_update_timers(call):
date_to = datetime.strftime((datetime.utcnow() + timedelta(days=1)), f"%Y-%m-%dT23:00:00Z")
rates_exc_peak.update(myrates.get_rates(date_from, date_to)["date_rates"])

avg_rate_exc_peak = round(sum(rates_exc_peak.values())/len(rates_exc_peak.values()), 2)
hass.states.set(f"octopusagile.avg_rate_exc_peak", avg_rate_exc_peak, {"unit_of_measurement": "p/kWh"})

jsonstr = json.dumps({
"timers":timer_list,
"rates":new_rates,
"all_rates": new_rates,
"avg_rate_exc_peak": avg_rate_exc_peak,
"avg_rate_inc_peak": avg_rate_inc_peak
})
f = open(datatorefile,"w")
f.write(jsonstr)
f.close()
if len(rates_exc_peak.values()) > 0:
avg_rate_exc_peak = round(sum(rates_exc_peak.values())/len(rates_exc_peak.values()), 2)
hass.states.set(f"octopusagile.avg_rate_exc_peak", avg_rate_exc_peak)

def handle_half_hour_timer(call):
"""Handle the service call."""
Expand Down Expand Up @@ -371,10 +362,6 @@ def handle_update_consumption(call):
round(monthlycost/100, 2),
attributes={'unit_of_measurement': '£',
'icon': 'mdi:cash'})
hourly, daily, hour_daily = myrates.aggregate_consumption()
hass.states.set(f"octopusagile.hourly_consumption", "", hourly)
hass.states.set(f"octopusagile.daily_consumption", "", daily)
hass.states.set(f"octopusagile.hour_daily_consumption", "", hour_daily)

def half_hour_timer(nowtime):
roundedtime = myrates.round_time(nowtime)
Expand Down

0 comments on commit f028530

Please sign in to comment.