Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/zones/DK-DK1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ parsers:
consumptionForecast: ENTSOE.fetch_consumption_forecast
generationForecast: ENTSOE.fetch_generation_forecast
price: NORDPOOL.fetch_price
production: ENTSOE.fetch_production
production: Energinet.fetch_production
productionCapacity: ENTSOE.fetch_production_capacity
productionPerModeForecast: DK.fetch_wind_solar_forecasts
region: Europe
Expand Down
2 changes: 1 addition & 1 deletion config/zones/DK-DK2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ parsers:
consumptionForecast: ENTSOE.fetch_consumption_forecast
generationForecast: ENTSOE.fetch_generation_forecast
price: NORDPOOL.fetch_price
production: ENTSOE.fetch_production
production: Energinet.fetch_production
productionCapacity: ENTSOE.fetch_production_capacity
productionPerModeForecast: DK.fetch_wind_solar_forecasts
region: Europe
Expand Down
80 changes: 80 additions & 0 deletions electricitymap/contrib/parsers/Energinet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from datetime import datetime, timedelta
from logging import Logger, getLogger
from zoneinfo import ZoneInfo

from requests import Session

from electricitymap.contrib.lib.models.event_lists import (
ProductionBreakdownList,
)
from electricitymap.contrib.lib.models.events import ProductionMix
from electricitymap.contrib.lib.types import ZoneKey

ENERGINET_API = "https://api.energidataservice.dk/dataset/GenerationProdTypeExchange"

ZONE_KEY_TO_PRICE_AREA = {
ZoneKey("DK-DK1"): "DK1",
ZoneKey("DK-DK2"): "DK2",
}

ENERGINET_TO_PRODUCTION_MIX_MAPPING = {
"OffshoreWindPower": "wind",
"OnshoreWindPower": "wind",
"HydroPower": "hydro",
"SolarPower": "solar",
"SolarPowerSelfCon": "solar",
"Biomass": "biomass",
"Biogas": "gas",
"Waste": "biomass",
"FossilGas": "gas",
"FossilOil": "oil",
"FossilHardCoal": "coal",
}


def fetch_production(
zone_key: ZoneKey,
session: Session | None = None,
target_datetime: datetime | None = None,
logger: Logger = getLogger(__name__),
) -> list[dict] | dict:
session = session or Session()

if target_datetime is None:
target_datetime = datetime.now(tz=ZoneInfo("Europe/Copenhagen"))
else:
target_datetime = target_datetime.astimezone(ZoneInfo("Europe/Copenhagen"))

start_datetime = target_datetime - timedelta(hours=24)
end_datetime = target_datetime + timedelta(hours=24)

response = session.get(
url=ENERGINET_API,
params={
"filter": f'{{"PriceArea":"{ZONE_KEY_TO_PRICE_AREA[zone_key]}"}}',
"start": start_datetime.strftime("%Y-%m-%dT%H:%M"),
"end": end_datetime.strftime("%Y-%m-%dT%H:%M"),
},
)

obj = response.json()

records = obj.get("records", [])

production_list = ProductionBreakdownList(logger=logger)
for record in records:
production_mix = ProductionMix()

for key, value in ENERGINET_TO_PRODUCTION_MIX_MAPPING.items():
production_mix.add_value(value, record[key])

production_list.append(
zoneKey=zone_key,
datetime=datetime.fromisoformat(record["TimeUTC"]).replace(
tzinfo=ZoneInfo("UTC")
),
production=production_mix,
source="energinet.dk",
)

return production_list.to_list()
Loading