Skip to content

Commit

Permalink
fix(sensors): Fixed handling the retrieving of tracker tariff data fo…
Browse files Browse the repository at this point in the history
…r non tracker tariffs
  • Loading branch information
BottlecapDave committed Jun 3, 2023
1 parent d83959f commit 6c277d4
Showing 1 changed file with 63 additions and 42 deletions.
105 changes: 63 additions & 42 deletions custom_components/octopus_energy/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ async def async_refresh_token(self):
url = f'{self._base_url}/v1/graphql/'
payload = { "query": api_token_query.format(api_key=self._api_key) }
async with client.post(url, json=payload) as token_response:
token_response_body = await self.__async_read_response(token_response, url)
token_response_body = await self.__async_read_response__(token_response, url)
if (token_response_body is not None and
"data" in token_response_body and
"obtainKrakenToken" in token_response_body["data"] and
Expand All @@ -261,7 +261,7 @@ async def async_get_account(self, account_id):
payload = { "query": account_query.format(account_id=account_id) }
headers = { "Authorization": f"JWT {self._graphql_token}" }
async with client.post(url, json=payload, headers=headers) as account_response:
account_response_body = await self.__async_read_response(account_response, url)
account_response_body = await self.__async_read_response__(account_response, url)

_LOGGER.debug(f'account: {account_response_body}')

Expand Down Expand Up @@ -364,7 +364,7 @@ async def async_get_saving_sessions(self, account_id):
payload = { "query": saving_session_query.format(account_id=account_id) }
headers = { "Authorization": f"JWT {self._graphql_token}" }
async with client.post(url, json=payload, headers=headers) as account_response:
response_body = await self.__async_read_response(account_response, url)
response_body = await self.__async_read_response__(account_response, url)

if (response_body is not None and "data" in response_body):
return {
Expand All @@ -389,7 +389,7 @@ async def async_get_smart_meter_consumption(self, device_id, period_from, period
payload = { "query": live_consumption_query.format(device_id=device_id, period_from=period_from, period_to=period_to) }
headers = { "Authorization": f"JWT {self._graphql_token}" }
async with client.post(url, json=payload, headers=headers) as live_consumption_response:
response_body = await self.__async_read_response(live_consumption_response, url)
response_body = await self.__async_read_response__(live_consumption_response, url)

if (response_body is not None and "data" in response_body and "smartMeterTelemetry" in response_body["data"] and response_body["data"]["smartMeterTelemetry"] is not None and len(response_body["data"]["smartMeterTelemetry"]) > 0):
return list(map(lambda mp: {
Expand All @@ -409,11 +409,14 @@ async def async_get_electricity_standard_rates(self, product_code, tariff_code,
auth = aiohttp.BasicAuth(self._api_key, '')
url = f'{self._base_url}/v1/products/{product_code}/electricity-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)
data = await self.__async_read_response__(response, url)
if data is None:
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._electricity_price_cap)

results = rates_to_thirty_minute_increments(data, period_from, period_to, tariff_code, self._electricity_price_cap)
if await self.__async_is_tracker_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)

return results

Expand All @@ -424,19 +427,22 @@ async def async_get_electricity_day_night_rates(self, product_code, tariff_code,
auth = aiohttp.BasicAuth(self._api_key, '')
url = f'{self._base_url}/v1/products/{product_code}/electricity-tariffs/{tariff_code}/day-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)
data = await self.__async_read_response__(response, url)
if data is None:
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._electricity_price_cap)

# Normalise the rates to be in 30 minute increments and remove any rates that fall outside of our day period
day_rates = rates_to_thirty_minute_increments(data, period_from, period_to, tariff_code, self._electricity_price_cap)
for rate in day_rates:
if (self.__is_night_rate(rate, is_smart_meter)) == False:
results.append(rate)
if await self.__async_is_tracker_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
day_rates = rates_to_thirty_minute_increments(data, period_from, period_to, tariff_code, self._electricity_price_cap)
for rate in day_rates:
if (self.__is_night_rate(rate, is_smart_meter)) == False:
results.append(rate)

url = f'{self._base_url}/v1/products/{product_code}/electricity-tariffs/{tariff_code}/night-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)
data = await self.__async_read_response__(response, url)
if data is None:
return None

Expand All @@ -460,7 +466,7 @@ async def async_get_electricity_rates(self, tariff_code, is_smart_meter, period_

product_code = tariff_parts.product_code

if (await self.__async_is_tracker_tariff(tariff_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")):
return await self.async_get_electricity_standard_rates(product_code, tariff_code, period_from, period_to)
Expand All @@ -474,7 +480,7 @@ async def async_get_electricity_consumption(self, mpan, serial_number, period_fr
url = f'{self._base_url}/v1/electricity-meter-points/{mpan}/meters/{serial_number}/consumption?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)
data = await self.__async_read_response__(response, url)
if (data is not None and "results" in data):
data = data["results"]
results = []
Expand All @@ -499,19 +505,22 @@ async def async_get_gas_rates(self, tariff_code, period_from, period_to):

product_code = tariff_parts.product_code

if (await self.__async_is_tracker_tariff(tariff_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)
data = await self.__async_read_response__(response, url)
if data is None:
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._gas_price_cap)
if await self.__async_is_tracker_product__(tariff_code):
return await self.__async_get_tracker_rates__(tariff_code, period_from, period_to, self._gas_price_cap)

results = rates_to_thirty_minute_increments(data, period_from, period_to, tariff_code, self._gas_price_cap)
return None
else:
results = rates_to_thirty_minute_increments(data, period_from, period_to, tariff_code, self._gas_price_cap)

return results

Expand All @@ -521,7 +530,7 @@ async def async_get_gas_consumption(self, mprn, serial_number, period_from, peri
auth = aiohttp.BasicAuth(self._api_key, '')
url = f'{self._base_url}/v1/gas-meter-points/{mprn}/meters/{serial_number}/consumption?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)
data = await self.__async_read_response__(response, url)
if (data is not None and "results" in data):
data = data["results"]
results = []
Expand All @@ -544,7 +553,7 @@ async def async_get_product(self, product_code):
auth = aiohttp.BasicAuth(self._api_key, '')
url = f'{self._base_url}/v1/products/{product_code}'
async with client.get(url, auth=auth) as response:
return await self.__async_read_response(response, url)
return await self.__async_read_response__(response, url)

async def async_get_electricity_standing_charge(self, tariff_code, period_from, period_to):
"""Get the electricity standing charges"""
Expand All @@ -554,19 +563,19 @@ async def async_get_electricity_standing_charge(self, tariff_code, period_from,

product_code = tariff_parts.product_code

if await self.__async_is_tracker_tariff(tariff_code):
if self.__is_tracker_tariff__(tariff_code):
return await self.__async_get_tracker_standing_charge__(tariff_code, period_from, period_to)

result = None
async with aiohttp.ClientSession() as client:
auth = aiohttp.BasicAuth(self._api_key, '')
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)
data = await self.__async_read_response__(response, url)
if data is None:
return await self.__async_get_tracker_standing_charge__(tariff_code, period_from, period_to)

if ("results" in data and len(data["results"]) > 0):
if await self.__async_is_tracker_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):
result = {
"value_inc_vat": float(data["results"][0]["value_inc_vat"])
}
Expand All @@ -581,19 +590,19 @@ async def async_get_gas_standing_charge(self, tariff_code, period_from, period_t

product_code = tariff_parts.product_code

if await self.__async_is_tracker_tariff(tariff_code):
if self.__is_tracker_tariff__(tariff_code):
return await self.__async_get_tracker_standing_charge__(tariff_code, period_from, period_to)

result = None
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}/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)
data = await self.__async_read_response__(response, url)
if data is None:
return await self.__async_get_tracker_standing_charge__(tariff_code, period_from, period_to)

if ("results" in data and len(data["results"]) > 0):
if await self.__async_is_tracker_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):
result = {
"value_inc_vat": float(data["results"][0]["value_inc_vat"])
}
Expand All @@ -610,7 +619,7 @@ async def async_get_intelligent_dispatches(self, account_id: str):
payload = { "query": intelligent_dispatches_query.format(account_id=account_id) }
headers = { "Authorization": f"JWT {self._graphql_token}" }
async with client.post(url, json=payload, headers=headers) as response:
response_body = await self.__async_read_response(response, url)
response_body = await self.__async_read_response__(response, url)

if (response_body is not None and "data" in response_body):
return {
Expand Down Expand Up @@ -644,7 +653,7 @@ async def async_get_intelligent_device(self, account_id: str):
payload = { "query": intelligent_device_query.format(account_id=account_id) }
headers = { "Authorization": f"JWT {self._graphql_token}" }
async with client.post(url, json=payload, headers=headers) as response:
response_body = await self.__async_read_response(response, url)
response_body = await self.__async_read_response__(response, url)

if (response_body is not None and "data" in response_body and
"registeredKrakenflexDevice" in response_body["data"]):
Expand All @@ -654,7 +663,7 @@ async def async_get_intelligent_device(self, account_id: str):

return None

async def __async_is_tracker_tariff(self, tariff_code):
def __is_tracker_tariff__(self, tariff_code):
tariff_parts = get_tariff_parts(tariff_code)
if tariff_parts is None:
return None
Expand All @@ -664,11 +673,23 @@ async def __async_is_tracker_tariff(self, tariff_code):
if product_code in self._product_tracker_cache:
return self._product_tracker_cache[product_code]

return False

async def __async_is_tracker_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)
data = await self.__async_read_response__(response, url)
if data == None:
return False

Expand All @@ -695,7 +716,7 @@ async def __async_get_tracker_rates__(self, tariff_code, period_from, period_to,
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)
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
Expand Down Expand Up @@ -733,7 +754,7 @@ async def __async_get_tracker_standing_charge__(self, tariff_code, period_from,
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)
data = await self.__async_read_response__(response, url)
except RequestError:
# This is thrown when the tariff isn't present
return None
Expand Down Expand Up @@ -792,7 +813,7 @@ def __process_consumption(self, item):
"interval_end": as_utc(parse_datetime(item["interval_end"]))
}

async def __async_read_response(self, response, url):
async def __async_read_response__(self, response, url):
"""Reads the response, logging any json errors"""

text = await response.text()
Expand Down

0 comments on commit 6c277d4

Please sign in to comment.