Skip to content

Commit e304022

Browse files
Add service in Nord Pool for fetching normalized price indices (home-assistant#147979)
1 parent 160e4e4 commit e304022

File tree

9 files changed

+1726
-9
lines changed

9 files changed

+1726
-9
lines changed

homeassistant/components/nordpool/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
DEFAULT_NAME = "Nord Pool"
1313

1414
CONF_AREAS = "areas"
15+
ATTR_RESOLUTION = "resolution"

homeassistant/components/nordpool/icons.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
"services": {
4343
"get_prices_for_date": {
4444
"service": "mdi:cash-multiple"
45+
},
46+
"get_price_indices_for_date": {
47+
"service": "mdi:cash-multiple"
4548
}
4649
}
4750
}

homeassistant/components/nordpool/services.py

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,21 @@
22

33
from __future__ import annotations
44

5+
from collections.abc import Callable
56
from datetime import date, datetime
7+
from functools import partial
68
import logging
79
from typing import TYPE_CHECKING
810

911
from pynordpool import (
1012
AREAS,
1113
Currency,
14+
DeliveryPeriodData,
1215
NordPoolAuthenticationError,
16+
NordPoolClient,
1317
NordPoolEmptyResponseError,
1418
NordPoolError,
19+
PriceIndicesData,
1520
)
1621
import voluptuous as vol
1722

@@ -32,14 +37,15 @@
3237

3338
if TYPE_CHECKING:
3439
from . import NordPoolConfigEntry
35-
from .const import DOMAIN
40+
from .const import ATTR_RESOLUTION, DOMAIN
3641

3742
_LOGGER = logging.getLogger(__name__)
3843
ATTR_CONFIG_ENTRY = "config_entry"
3944
ATTR_AREAS = "areas"
4045
ATTR_CURRENCY = "currency"
4146

4247
SERVICE_GET_PRICES_FOR_DATE = "get_prices_for_date"
48+
SERVICE_GET_PRICE_INDICES_FOR_DATE = "get_price_indices_for_date"
4349
SERVICE_GET_PRICES_SCHEMA = vol.Schema(
4450
{
4551
vol.Required(ATTR_CONFIG_ENTRY): ConfigEntrySelector({"integration": DOMAIN}),
@@ -50,6 +56,13 @@
5056
),
5157
}
5258
)
59+
SERVICE_GET_PRICE_INDICES_SCHEMA = SERVICE_GET_PRICES_SCHEMA.extend(
60+
{
61+
vol.Optional(ATTR_RESOLUTION, default=60): vol.All(
62+
cv.positive_int, vol.All(vol.Coerce(int), vol.In((15, 30, 60)))
63+
),
64+
}
65+
)
5366

5467

5568
def get_config_entry(hass: HomeAssistant, entry_id: str) -> NordPoolConfigEntry:
@@ -71,11 +84,13 @@ def get_config_entry(hass: HomeAssistant, entry_id: str) -> NordPoolConfigEntry:
7184
def async_setup_services(hass: HomeAssistant) -> None:
7285
"""Set up services for Nord Pool integration."""
7386

74-
async def get_prices_for_date(call: ServiceCall) -> ServiceResponse:
75-
"""Get price service."""
87+
def get_service_params(
88+
call: ServiceCall,
89+
) -> tuple[NordPoolClient, date, str, list[str], int]:
90+
"""Return the parameters for the service."""
7691
entry = get_config_entry(hass, call.data[ATTR_CONFIG_ENTRY])
77-
asked_date: date = call.data[ATTR_DATE]
7892
client = entry.runtime_data.client
93+
asked_date: date = call.data[ATTR_DATE]
7994

8095
areas: list[str] = entry.data[ATTR_AREAS]
8196
if _areas := call.data.get(ATTR_AREAS):
@@ -85,14 +100,55 @@ async def get_prices_for_date(call: ServiceCall) -> ServiceResponse:
85100
if _currency := call.data.get(ATTR_CURRENCY):
86101
currency = _currency
87102

103+
resolution: int = 60
104+
if _resolution := call.data.get(ATTR_RESOLUTION):
105+
resolution = _resolution
106+
88107
areas = [area.upper() for area in areas]
89108
currency = currency.upper()
90109

110+
return (client, asked_date, currency, areas, resolution)
111+
112+
async def get_prices_for_date(
113+
client: NordPoolClient,
114+
asked_date: date,
115+
currency: str,
116+
areas: list[str],
117+
resolution: int,
118+
) -> DeliveryPeriodData:
119+
"""Get prices."""
120+
return await client.async_get_delivery_period(
121+
datetime.combine(asked_date, dt_util.utcnow().time()),
122+
Currency(currency),
123+
areas,
124+
)
125+
126+
async def get_price_indices_for_date(
127+
client: NordPoolClient,
128+
asked_date: date,
129+
currency: str,
130+
areas: list[str],
131+
resolution: int,
132+
) -> PriceIndicesData:
133+
"""Get prices."""
134+
return await client.async_get_price_indices(
135+
datetime.combine(asked_date, dt_util.utcnow().time()),
136+
Currency(currency),
137+
areas,
138+
resolution=resolution,
139+
)
140+
141+
async def get_prices(func: Callable, call: ServiceCall) -> ServiceResponse:
142+
"""Get price service."""
143+
client, asked_date, currency, areas, resolution = get_service_params(call)
144+
91145
try:
92-
price_data = await client.async_get_delivery_period(
93-
datetime.combine(asked_date, dt_util.utcnow().time()),
94-
Currency(currency),
146+
price_data = await func(
147+
client,
148+
asked_date,
149+
currency,
95150
areas,
151+
resolution,
96152
)
97153
except NordPoolAuthenticationError as error:
98154
raise ServiceValidationError(
@@ -122,7 +178,14 @@ async def get_prices_for_date(call: ServiceCall) -> ServiceResponse:
122178
hass.services.async_register(
123179
DOMAIN,
124180
SERVICE_GET_PRICES_FOR_DATE,
125-
get_prices_for_date,
181+
partial(get_prices, get_prices_for_date),
126182
schema=SERVICE_GET_PRICES_SCHEMA,
127183
supports_response=SupportsResponse.ONLY,
128184
)
185+
hass.services.async_register(
186+
DOMAIN,
187+
SERVICE_GET_PRICE_INDICES_FOR_DATE,
188+
partial(get_prices, get_price_indices_for_date),
189+
schema=SERVICE_GET_PRICE_INDICES_SCHEMA,
190+
supports_response=SupportsResponse.ONLY,
191+
)

homeassistant/components/nordpool/services.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,59 @@ get_prices_for_date:
4646
- "PLN"
4747
- "SEK"
4848
mode: dropdown
49+
get_price_indices_for_date:
50+
fields:
51+
config_entry:
52+
required: true
53+
selector:
54+
config_entry:
55+
integration: nordpool
56+
date:
57+
required: true
58+
selector:
59+
date:
60+
areas:
61+
selector:
62+
select:
63+
options:
64+
- "EE"
65+
- "LT"
66+
- "LV"
67+
- "AT"
68+
- "BE"
69+
- "FR"
70+
- "GER"
71+
- "NL"
72+
- "PL"
73+
- "DK1"
74+
- "DK2"
75+
- "FI"
76+
- "NO1"
77+
- "NO2"
78+
- "NO3"
79+
- "NO4"
80+
- "NO5"
81+
- "SE1"
82+
- "SE2"
83+
- "SE3"
84+
- "SE4"
85+
- "SYS"
86+
mode: dropdown
87+
currency:
88+
selector:
89+
select:
90+
options:
91+
- "DKK"
92+
- "EUR"
93+
- "NOK"
94+
- "PLN"
95+
- "SEK"
96+
mode: dropdown
97+
resolution:
98+
selector:
99+
select:
100+
options:
101+
- "15"
102+
- "30"
103+
- "60"
104+
mode: dropdown

homeassistant/components/nordpool/strings.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,32 @@
114114
"description": "Currency to get prices in. If left empty it will use the currency already configured."
115115
}
116116
}
117+
},
118+
"get_price_indices_for_date": {
119+
"name": "Get price indices for date",
120+
"description": "Retrieves the price indices for a specific date.",
121+
"fields": {
122+
"config_entry": {
123+
"name": "Config entry",
124+
"description": "The Nord Pool configuration entry for this action."
125+
},
126+
"date": {
127+
"name": "Date",
128+
"description": "Only dates two months in the past and one day in the future is allowed."
129+
},
130+
"areas": {
131+
"name": "Areas",
132+
"description": "One or multiple areas to get prices for. If left empty it will use the areas already configured."
133+
},
134+
"currency": {
135+
"name": "Currency",
136+
"description": "Currency to get prices in. If left empty it will use the currency already configured."
137+
},
138+
"resolution": {
139+
"name": "Resolution",
140+
"description": "Resolution time for the prices, can be any of 15, 30 and 60 minutes."
141+
}
142+
}
117143
}
118144
},
119145
"exceptions": {

0 commit comments

Comments
 (0)