Skip to content

Commit

Permalink
Added demand day ahead forecast
Browse files Browse the repository at this point in the history
  • Loading branch information
JRascagneres committed Dec 17, 2023
1 parent adf6977 commit b22de10
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 6 deletions.
30 changes: 25 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,10 @@ Thirty minute long term wind forecast - From now to three days ahead

Name - Embedded Wind Forecast Three Day\
ID - sensor.national_grid_embedded_wind_forecast_three_day\
State - None\
State - Closest forecasted value to 'now'
Attributes:
```
current_value:
forecast:
- start_time: ...
generation: ...
Expand All @@ -203,9 +204,10 @@ Two-hourly long term wind forecast - From now to fourteen days ahead

Name - Embedded Wind Forecast Fourteen Day\
ID - sensor.national_grid_embedded_wind_forecast_fourteen_day\
State - None\
State - Closest forecasted value to 'now'
Attributes:
```
current_value:
forecast:
- start_time: ...
generation: ...
Expand All @@ -217,29 +219,47 @@ Thirty minute long term wind forecast - From now to three days ahead

Name - Embedded Solar Forecast Three Day\
ID - sensor.national_grid_embedded_solar_forecast_three_day\
State - None\
State - Closest forecasted value to 'now'
Attributes:
```
current_value:
forecast:
- start_time: ...
generation: ...
...
```

### Embedded Solar Forecast Seven To Fourteen Day Entity
### Embedded Solar Forecast Fourteen Day Entity
Two-hourly long term solar forecast - From now to fourteen days ahead

Name - Embedded Solar Forecast Fourteen Day\
ID - sensor.national_grid_embedded_solar_forecast_fourteen_day\
State - None\
State - Closest forecasted value to 'now'
Attributes:
```
current_value:
forecast:
- start_time: ...
generation: ...
...
```

### National Grid Grid Demand Day Ahead Forecast Entity
Thirty minute day ahead demand forecast

Name - Grid Demand Day Ahead Forecast
ID - sensor.national_grid_grid_demand_day_ahead_forecast
State - Closest forecasted value to 'now'
Attributes:
```
current_value:
forecast:
- start_time: ...
transmission_demand: ...
national_demand: ...
...
```

## Uses / Examples
This section outlines some graphs / views I have personally created with the data provided by the integration.

Expand Down
54 changes: 54 additions & 0 deletions custom_components/national_grid/coordinators/national_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
NationalGridWindForecast,
NationalGridWindForecastLongTerm,
NationalGridWindForecastItem,
NationalGridDemandForecastItem,
NationalGridDemandForecast,
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -131,6 +133,8 @@ def get_data(
wind,
) = get_long_term_embedded_wind_and_solar_forecast(today_full)

demand_day_ahead_forecast = get_demand_day_ahead_forecast(now_utc_full)

return NationalGridData(
sell_price=current_price,
carbon_intensity=carbon_intensity,
Expand All @@ -145,6 +149,7 @@ def get_data(
fourteen_embedded_wind=wind,
three_embedded_wind=three_day_wind,
grid_generation=grid_generation,
grid_demand_day_ahead_forecast=demand_day_ahead_forecast,
total_demand_mwh=total_demand_mwh,
total_transfers_mwh=total_transfers_mwh,
)
Expand Down Expand Up @@ -386,6 +391,55 @@ def get_wind_data(today: str, tomorrow: str) -> NationalGridWindData:
)


def get_demand_day_ahead_forecast(utc_now: datetime) -> NationalGridDemandForecast:
utc_now_formatted = utc_now.strftime("%Y-%m-%dT%H:%M:%SZ")
two_days = (utc_now + timedelta(days=2)).strftime("%Y-%m-%dT%H:%M:%SZ")

nearest_30_minutes = utc_now + (
utc_now.min.replace(tzinfo=utc_now.tzinfo) - utc_now
) % timedelta(minutes=30)

url = (
"https://data.elexon.co.uk/bmrs/api/v1/forecast/demand/day-ahead/latest?format=json&from="
+ utc_now_formatted
+ "&to="
+ two_days
+ "&boundary=N"
)

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

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

current = 0
forecast = []

for item in items:
transmission_demand = item["transmissionSystemDemand"]
national_demand = item["nationalDemand"]
start_time_datetime = datetime.strptime(
item["startTime"], "%Y-%m-%dT%H:%M:%S%z"
)

if start_time_datetime == nearest_30_minutes:
current = national_demand

forecast.append(
NationalGridDemandForecastItem(
start_time=start_time_datetime,
transmission_demand=transmission_demand,
national_demand=national_demand,
)
)

return NationalGridDemandForecast(
current_value=current,
forecast=forecast,
)


def get_national_grid_data(today_utc: str, now_utc: datetime) -> dict[str, Any]:
today_minutes = now_utc.hour * 60 + now_utc.minute
settlement_period = (today_minutes // 30) + 1
Expand Down
2 changes: 1 addition & 1 deletion custom_components/national_grid/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"dependencies": [],
"iot_class": "cloud_polling",
"requirements": [],
"version": "0.0.33",
"version": "0.0.34",
"config_flow": true
}
12 changes: 12 additions & 0 deletions custom_components/national_grid/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ class NationalGridSolarForecast(TypedDict):
forecast: list[NationalGridSolarForecastItem]


class NationalGridDemandForecastItem(TypedDict):
start_time: datetime
transmission_demand: int
national_demand: int


class NationalGridDemandForecast(TypedDict):
current_value: int
forecast: list[NationalGridDemandForecastItem]


class NationalGridData(TypedDict):
sell_price: float
carbon_intensity: int
Expand All @@ -74,5 +85,6 @@ class NationalGridData(TypedDict):
three_embedded_wind: NationalGridWindForecast
fourteen_embedded_wind: NationalGridWindForecast
grid_generation: NationalGridGeneration
grid_demand_day_ahead_forecast: NationalGridDemandForecast
total_demand_mwh: int
total_transfers_mwh: int
9 changes: 9 additions & 0 deletions custom_components/national_grid/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,15 @@ class NationalGridSensorEntityDescription(SensorEntityDescription):
state_class=SensorStateClass.MEASUREMENT,
extra_attributes_key="three_embedded_wind",
),
NationalGridSensorEntityDescription(
key="grid_demand_day_ahead_forecast.current_value",
name="Grid Demand Day Ahead Forecast",
unique_id="grid_demand_day_ahead_forecast",
native_unit_of_measurement="MW",
icon="mdi:transmission-tower",
state_class=SensorStateClass.MEASUREMENT,
extra_attributes_key="grid_demand_day_ahead_forecast",
),
NationalGridSensorEntityDescription(
key=None,
name="Grid Generation",
Expand Down

0 comments on commit b22de10

Please sign in to comment.