Skip to content

Commit

Permalink
Added DFS Requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
JRascagneres committed Dec 18, 2023
1 parent b22de10 commit 074bf7e
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 4 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,25 @@ forecast:
...
```

### National Grid DFS Requirements Entity
National Grid DFS Requirements - Shows last 15 only

Name - National Grid DFS Requirements
ID - sensor.national_grid_dfs_requirements
State - National Grid DFS Requirements
Attributes:
```
requirements:
- start_time: ...
end_time: ...
required_mw: ...
requirement_type: ...
despatch_type: ...
participants_eligible:
- ...
...
```

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

Expand Down
53 changes: 50 additions & 3 deletions custom_components/national_grid/coordinators/national_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
NationalGridWindForecastItem,
NationalGridDemandForecastItem,
NationalGridDemandForecast,
DFSRequirements,
DFSRequirementItem,
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -133,7 +135,16 @@ 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)
demand_day_ahead_forecast = obtain_data_with_fallback(
current_data,
"grid_demand_day_ahead_forecast",
get_demand_day_ahead_forecast,
now_utc_full,
)

dfs_requirements = obtain_data_with_fallback(
current_data, "dfs_requirements", get_dfs_requirements
)

return NationalGridData(
sell_price=current_price,
Expand All @@ -144,14 +155,15 @@ def get_data(
now_to_three_wind_forecast=three_day,
fourteen_wind_forecast=fourteen_day,
solar_forecast=solar_forecast,
fourteen_embedded_solar=solar,
three_embedded_solar=three_day_solar,
fourteen_embedded_wind=wind,
fourteen_embedded_solar=solar,
three_embedded_wind=three_day_wind,
fourteen_embedded_wind=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,
dfs_requirements=dfs_requirements,
)


Expand Down Expand Up @@ -636,6 +648,41 @@ def get_long_term_embedded_wind_and_solar_forecast(
return (three_day_solar, solar, three_day_wind, wind)


def get_dfs_requirements() -> DFSRequirements:
url = "https://api.nationalgrideso.com/api/3/action/datastore_search?resource_id=7914dd99-fe1c-41ba-9989-5784531c58bb&limit=15&sort=_id%20desc"
response = requests.get(url, timeout=20)
data = json.loads(response.content)

all_requirements = []

all_records = data["result"]["records"]
for record in all_records:
participants_eligible = record["Participant Bids Eligible"].split(",")

start_time = datetime.strptime(
record["Delivery Date"] + "T" + record["From"], "%Y-%m-%dT%H:%M:%S"
).replace(tzinfo=tz.UTC)

end_time = datetime.strptime(
record["Delivery Date"] + "T" + record["To"], "%Y-%m-%dT%H:%M:%S"
).replace(tzinfo=tz.UTC)

all_requirements.append(
DFSRequirementItem(
start_time=start_time,
end_time=end_time,
required_mw=record["DFS Required MW"],
requirement_type=record["Service Requirement Type"],
despatch_type=record["Despatch Type"],
participants_eligible=participants_eligible,
)
)

dfs_requirements = DFSRequirements(requirements=all_requirements)

return dfs_requirements


def get_carbon_intensity(now_utc_full: datetime) -> int:
formatted_datetime = now_utc_full.strftime("%Y-%m-%dT%H:%MZ")
url = (
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.34",
"version": "0.0.35",
"config_flow": true
}
19 changes: 19 additions & 0 deletions custom_components/national_grid/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,39 @@ class NationalGridDemandForecast(TypedDict):
forecast: list[NationalGridDemandForecastItem]


class DFSRequirementItem(TypedDict):
start_time: datetime
end_time: datetime
required_mw: int
requirement_type: str
despatch_type: str
participants_eligible: list[str]


class DFSRequirements(TypedDict):
requirements: list[DFSRequirementItem]


class NationalGridData(TypedDict):
sell_price: float
carbon_intensity: int

wind_data: NationalGridWindData
wind_forecast: NationalGridWindForecast
wind_forecast_earliest: NationalGridWindForecast

now_to_three_wind_forecast: NationalGridWindForecastLongTerm
fourteen_wind_forecast: NationalGridWindForecastLongTerm
solar_forecast: NationalGridSolarForecast
three_embedded_solar: NationalGridSolarForecast
fourteen_embedded_solar: NationalGridSolarForecast
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

dfs_requirements: DFSRequirements
7 changes: 7 additions & 0 deletions custom_components/national_grid/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,13 @@ class NationalGridSensorEntityDescription(SensorEntityDescription):
state_class=SensorStateClass.MEASUREMENT,
extra_attributes_key="grid_demand_day_ahead_forecast",
),
NationalGridSensorEntityDescription(
key=None,
name="DFS Requirements",
unique_id="dfs_requirements",
icon="mdi:leaf",
extra_attributes_key="dfs_requirements",
),
NationalGridSensorEntityDescription(
key=None,
name="Grid Generation",
Expand Down

0 comments on commit 074bf7e

Please sign in to comment.