Skip to content

Commit

Permalink
fix(api-client): removed tracker fall-back API
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
While this shouldn't have a negative effect on anyone, I'm marking the removal of the tracker
fallback API as a breaking change. This is because I believe it's cause bugs to be raised and there
are several threads within the OE forums that don't suggest using it for various reasons
https://forum.octopus.energy/t/finding-the-latest-gas-tracker-api/6021/9. This original tariff that
introduced this work around is now properly supported by the API.
  • Loading branch information
BottlecapDave committed Aug 4, 2023
1 parent fafb031 commit fd095cb
Showing 1 changed file with 3 additions and 122 deletions.
125 changes: 3 additions & 122 deletions custom_components/octopus_energy/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,9 +489,6 @@ async def async_get_electricity_standard_rates(self, product_code, tariff_code,
async with client.get(url, auth=auth) as response:
data = await self.__async_read_response__(response, url)
if data is None:
if await self.__async_is_tracker_tariff_or_product__(tariff_code):
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._electricity_price_cap)

return None
else:
results = rates_to_thirty_minute_increments(data, period_from, period_to, tariff_code, self._electricity_price_cap)
Expand All @@ -507,9 +504,6 @@ async def async_get_electricity_day_night_rates(self, product_code, tariff_code,
async with client.get(url, auth=auth) as response:
data = await self.__async_read_response__(response, url)
if data is None:
if await self.__async_is_tracker_tariff_or_product__(tariff_code):
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._electricity_price_cap)

return None
else:
# Normalise the rates to be in 30 minute increments and remove any rates that fall outside of our day period
Expand Down Expand Up @@ -544,9 +538,7 @@ async def async_get_electricity_rates(self, tariff_code, is_smart_meter, period_

product_code = tariff_parts.product_code

if (self.__is_tracker_tariff__(tariff_code)):
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._electricity_price_cap)
elif (tariff_parts.rate.startswith("1")):
if (tariff_parts.rate.startswith("1")):
return await self.async_get_electricity_standard_rates(product_code, tariff_code, period_from, period_to)
else:
return await self.async_get_electricity_day_night_rates(product_code, tariff_code, is_smart_meter, period_from, period_to)
Expand Down Expand Up @@ -583,19 +575,13 @@ async def async_get_gas_rates(self, tariff_code, period_from, period_to):

product_code = tariff_parts.product_code

if (self.__is_tracker_tariff__(tariff_code)):
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._gas_price_cap)

results = []
async with aiohttp.ClientSession() as client:
auth = aiohttp.BasicAuth(self._api_key, '')
url = f'{self._base_url}/v1/products/{product_code}/gas-tariffs/{tariff_code}/standard-unit-rates?period_from={period_from.strftime("%Y-%m-%dT%H:%M:%SZ")}&period_to={period_to.strftime("%Y-%m-%dT%H:%M:%SZ")}'
async with client.get(url, auth=auth) as response:
data = await self.__async_read_response__(response, url)
if data is None:
if await self.__async_is_tracker_tariff_or_product__(tariff_code):
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._gas_price_cap)

return None
else:
results = rates_to_thirty_minute_increments(data, period_from, period_to, tariff_code, self._gas_price_cap)
Expand Down Expand Up @@ -650,10 +636,7 @@ async def async_get_electricity_standing_charge(self, tariff_code, period_from,
url = f'{self._base_url}/v1/products/{product_code}/electricity-tariffs/{tariff_code}/standing-charges?period_from={period_from.strftime("%Y-%m-%dT%H:%M:%SZ")}&period_to={period_to.strftime("%Y-%m-%dT%H:%M:%SZ")}'
async with client.get(url, auth=auth) as response:
data = await self.__async_read_response__(response, url)
if data is None:
if await self.__async_is_tracker_tariff_or_product__(tariff_code):
return await self.__async_get_tracker_standing_charge__(tariff_code, period_from, period_to)
elif ("results" in data and len(data["results"]) > 0):
if (data is not None and "results" in data and len(data["results"]) > 0):
result = {
"valid_from": parse_datetime(data["results"][0]["valid_from"]) if "valid_from" in data["results"][0] and data["results"][0]["valid_from"] is not None else None,
"valid_to": parse_datetime(data["results"][0]["valid_to"]) if "valid_to" in data["results"][0] and data["results"][0]["valid_to"] is not None else None,
Expand All @@ -679,10 +662,7 @@ async def async_get_gas_standing_charge(self, tariff_code, period_from, period_t
url = f'{self._base_url}/v1/products/{product_code}/gas-tariffs/{tariff_code}/standing-charges?period_from={period_from.strftime("%Y-%m-%dT%H:%M:%SZ")}&period_to={period_to.strftime("%Y-%m-%dT%H:%M:%SZ")}'
async with client.get(url, auth=auth) as response:
data = await self.__async_read_response__(response, url)
if data is None:
if await self.__async_is_tracker_tariff_or_product__(tariff_code):
return await self.__async_get_tracker_standing_charge__(tariff_code, period_from, period_to)
elif ("results" in data and len(data["results"]) > 0):
if (data is not None and "results" in data and len(data["results"]) > 0):
result = {
"valid_from": parse_datetime(data["results"][0]["valid_from"]) if "valid_from" in data["results"][0] and data["results"][0]["valid_from"] is not None else None,
"valid_to": parse_datetime(data["results"][0]["valid_to"]) if "valid_to" in data["results"][0] and data["results"][0]["valid_to"] is not None else None,
Expand Down Expand Up @@ -899,105 +879,6 @@ def __is_tracker_tariff__(self, tariff_code):
return self._product_tracker_cache[product_code]

return False

async def __async_is_tracker_tariff_or_product__(self, tariff_code):
tariff_parts = get_tariff_parts(tariff_code)
if tariff_parts is None:
return None

product_code = tariff_parts.product_code

if self.__is_tracker_tariff__(tariff_code):
return True

async with aiohttp.ClientSession() as client:
auth = aiohttp.BasicAuth(self._api_key, '')
url = f'https://api.octopus.energy/v1/products/{product_code}'
async with client.get(url, auth=auth) as response:
data = await self.__async_read_response__(response, url)
if data == None:
return False

# Just because a product states its a tracker, it may go through the normal APIs or it may go through
# the bespoke tracker api, so we can't assume anything from a tracker cache perspective
is_tracker = "is_tracker" in data and data["is_tracker"]
return is_tracker

async def __async_get_tracker_rates__(self, tariff_code, period_from, period_to, price_cap: float = None):
"""Get the tracker rates"""
tariff_parts = get_tariff_parts(tariff_code)
if tariff_parts is None:
return None

product_code = tariff_parts.product_code

# If we know our tariff is not a tracker rate, then don't bother asking
if product_code in self._product_tracker_cache and self._product_tracker_cache[product_code] == False:
return None

results = []
async with aiohttp.ClientSession() as client:
auth = aiohttp.BasicAuth(self._api_key, '')
url = f'https://octopus.energy/api/v1/tracker/{tariff_code}/daily/past/1/0'
async with client.get(url, auth=auth) as response:
try:
data = await self.__async_read_response__(response, url)
except RequestError:
# This is thrown when the tariff isn't present
self._product_tracker_cache[product_code] = False
return None

if data is None:
# This is thrown when the tariff isn't present
self._product_tracker_cache[product_code] = False
return None

items = []
for period in data["periods"]:
valid_from = parse_datetime(f'{period["date"]}T00:00:00Z')
valid_to = parse_datetime(f'{period["date"]}T00:00:00Z') + timedelta(days=1)

if ((valid_from >= period_from and valid_from <= period_to) or (valid_to >= period_from and valid_to <= period_to)):
items.append(
{
"valid_from": valid_from.strftime("%Y-%m-%dT%H:%M:%SZ"),
"valid_to": valid_to.strftime("%Y-%m-%dT%H:%M:%SZ"),
"value_inc_vat": float(period["unit_rate"]),
}
)

results = rates_to_thirty_minute_increments({ "results": items }, period_from, period_to, tariff_code, price_cap)
self._product_tracker_cache[product_code] = True

return results

async def __async_get_tracker_standing_charge__(self, tariff_code, period_from, period_to):
"""Get the tracker standing charge"""

async with aiohttp.ClientSession() as client:
auth = aiohttp.BasicAuth(self._api_key, '')
url = f'https://octopus.energy/api/v1/tracker/{tariff_code}/daily/past/1/0'
async with client.get(url, auth=auth) as response:
try:
data = await self.__async_read_response__(response, url)
except RequestError:
# This is thrown when the tariff isn't present
return None

if data is None:
return None

for period in data["periods"]:
valid_from = parse_datetime(f'{period["date"]}T00:00:00Z')
valid_to = parse_datetime(f'{period["date"]}T00:00:00Z') + timedelta(days=1)
if ((valid_from >= period_from and valid_from <= period_to) or (valid_to >= period_from and valid_to <= period_to)):
return {
"valid_from": parse_datetime(period["valid_from"]),
"valid_to": parse_datetime(period["valid_to"]),
"value_inc_vat": float(period["standing_charge"])
}

return None

def __get_interval_end(self, item):
return item["interval_end"]
Expand Down

0 comments on commit fd095cb

Please sign in to comment.