Skip to content

Commit

Permalink
Update to new BMRS API
Browse files Browse the repository at this point in the history
  • Loading branch information
JRascagneres committed Jun 1, 2024
1 parent d732c7c commit 9a42f1f
Showing 1 changed file with 30 additions and 70 deletions.
100 changes: 30 additions & 70 deletions custom_components/national_grid/coordinators/national_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def get_data(
"""Get data."""
api_key = config[API_KEY]

yesterday_utc = (dt_util.utcnow() - timedelta(days=1)).strftime("%Y-%m-%d")
today_utc = dt_util.utcnow().strftime("%Y-%m-%d")

today = dt_util.now().strftime("%Y-%m-%d")
Expand All @@ -81,7 +82,12 @@ def get_data(
solar_forecast = None
if config[API_KEY_PROVIDED]:
current_price = obtain_data_with_fallback(
current_data, "sell_price", get_current_price, api_key, today_utc
current_data,
"sell_price",
get_current_price,
api_key,
today_utc,
yesterday_utc,
)
solar_forecast = obtain_data_with_fallback(
current_data,
Expand Down Expand Up @@ -363,20 +369,17 @@ def get_half_hourly_solar_forecast(
tomorrow = now + timedelta(days=1)
day_after_tomorrow = now + timedelta(days=2)

times = [yesterday, now, tomorrow, day_after_tomorrow]
results = []
for date in times:
date_format = date.strftime("%Y-%m-%d")
url = (
"https://api.bmreports.com/BMRS/B1440/v1?APIKey="
+ api_key
+ "&SettlementDate="
+ date_format
+ "&Period=*"
)
url = (
"https://data.elexon.co.uk/bmrs/api/v1/forecast/generation/wind-and-solar/day-ahead?from="
+ yesterday.strftime("%Y-%m-%d")
+ "&to="
+ day_after_tomorrow.strftime("%Y-%m-%d")
+ "&processType=all"
+ "&format=json"
)

response = get_bmrs_data_items(url)
results = results + response
response = requests.get(url, timeout=10)
results = json.loads(response.content)["data"]

unique_date_list = []
forecast = []
Expand All @@ -388,7 +391,7 @@ def get_half_hourly_solar_forecast(
settlementDate = item["settlementDate"]
settlementPeriod = item["settlementPeriod"]

unique_key = settlementDate + settlementPeriod
unique_key = str(settlementDate) + str(settlementPeriod)
if unique_key in unique_date_list:
continue

Expand Down Expand Up @@ -417,20 +420,22 @@ def get_half_hourly_solar_forecast(
)


def get_current_price(api_key: str, today_utc: str) -> float:
def get_current_price(api_key: str, today_utc: str, yesterday_utc: str) -> float:
"""Get current grid price."""
url = (
"https://api.bmreports.com/BMRS/DERSYSDATA/v1?APIKey="
+ api_key
+ "&FromSettlementDate="
+ today_utc
+ "&ToSettlementDate="
"https://data.elexon.co.uk/bmrs/api/v1/balancing/pricing/market-index?from="
+ yesterday_utc
+ "&to="
+ today_utc
+ "&SettlementPeriod=*"
+ "&dataProviders=APXMIDP&format=json"
)
latestResponse = get_bmrs_data_latest(url)
currentPrice = round(float(latestResponse["systemSellPrice"]), 2)
return currentPrice

response = requests.get(url, timeout=10)
items = json.loads(response.content)["data"]
if len(items) == 0:
raise UnexpectedDataError(url)

return round(float(items[0]["price"]), 2)


def get_current_frequency(api_key: str, now_utc: datetime) -> float:
Expand Down Expand Up @@ -1179,51 +1184,6 @@ def get_transfers(grid_generation: NationalGridGeneration):
)


def get_bmrs_data(url: str) -> OrderedDict[str, Any]:
"""Get BMRS data."""
response = requests.get(url, timeout=10)
data = xmltodict.parse(response.content)

if int(data["response"]["responseMetadata"]["httpCode"]) == 403:
raise InvalidAuthError

return data


def get_bmrs_data_items(url: str) -> OrderedDict[str, Any]:
"""Get BMRS data items."""
data = get_bmrs_data(url)
if data["response"]["responseMetadata"]["httpCode"] == "204":
return []

if (
"response" not in data
or "responseBody" not in data["response"]
or "responseList" not in data["response"]["responseBody"]
):
raise UnexpectedDataError(url)

responseList = data["response"]["responseBody"]["responseList"]
items = responseList["item"]
if type(items) is not list:
items = [items]

return items


def get_bmrs_data_latest(url: str) -> OrderedDict[str, Any]:
"""Get latest BMRS data."""

items = get_bmrs_data_items(url)

if len(items) == 0:
raise UnexpectedDataError(url)

latestResponse = items[len(items) - 1]

return latestResponse


def obtain_data_with_fallback(current_data, key, func, *args):
"""Obtain data with fallback."""
try:
Expand Down

0 comments on commit 9a42f1f

Please sign in to comment.