Home Assistant Unofficial Reference 2024.12.1
services.py
Go to the documentation of this file.
1 """The EnergyZero services."""
2 
3 from __future__ import annotations
4 
5 from datetime import date, datetime
6 from enum import Enum
7 from functools import partial
8 from typing import Final
9 
10 from energyzero import Electricity, Gas, VatOption
11 import voluptuous as vol
12 
13 from homeassistant.config_entries import ConfigEntry, ConfigEntryState
14 from homeassistant.core import (
15  HomeAssistant,
16  ServiceCall,
17  ServiceResponse,
18  SupportsResponse,
19  callback,
20 )
21 from homeassistant.exceptions import ServiceValidationError
22 from homeassistant.helpers import selector
23 from homeassistant.util import dt as dt_util
24 
25 from .const import DOMAIN
26 from .coordinator import EnergyZeroDataUpdateCoordinator
27 
28 ATTR_CONFIG_ENTRY: Final = "config_entry"
29 ATTR_START: Final = "start"
30 ATTR_END: Final = "end"
31 ATTR_INCL_VAT: Final = "incl_vat"
32 
33 GAS_SERVICE_NAME: Final = "get_gas_prices"
34 ENERGY_SERVICE_NAME: Final = "get_energy_prices"
35 SERVICE_SCHEMA: Final = vol.Schema(
36  {
37  vol.Required(ATTR_CONFIG_ENTRY): selector.ConfigEntrySelector(
38  {
39  "integration": DOMAIN,
40  }
41  ),
42  vol.Required(ATTR_INCL_VAT): bool,
43  vol.Optional(ATTR_START): str,
44  vol.Optional(ATTR_END): str,
45  }
46 )
47 
48 
49 class PriceType(Enum):
50  """Type of price."""
51 
52  ENERGY = "energy"
53  GAS = "gas"
54 
55 
56 def __get_date(date_input: str | None) -> date | datetime:
57  """Get date."""
58  if not date_input:
59  return dt_util.now().date()
60 
61  if value := dt_util.parse_datetime(date_input):
62  return value
63 
65  translation_domain=DOMAIN,
66  translation_key="invalid_date",
67  translation_placeholders={
68  "date": date_input,
69  },
70  )
71 
72 
73 def __serialize_prices(prices: Electricity | Gas) -> ServiceResponse:
74  """Serialize prices."""
75  return {
76  "prices": [
77  {
78  key: str(value) if isinstance(value, datetime) else value
79  for key, value in timestamp_price.items()
80  }
81  for timestamp_price in prices.timestamp_prices
82  ]
83  }
84 
85 
87  hass: HomeAssistant, call: ServiceCall
88 ) -> EnergyZeroDataUpdateCoordinator:
89  """Get the coordinator from the entry."""
90  entry_id: str = call.data[ATTR_CONFIG_ENTRY]
91  entry: ConfigEntry | None = hass.config_entries.async_get_entry(entry_id)
92 
93  if not entry:
95  translation_domain=DOMAIN,
96  translation_key="invalid_config_entry",
97  translation_placeholders={
98  "config_entry": entry_id,
99  },
100  )
101  if entry.state != ConfigEntryState.LOADED:
103  translation_domain=DOMAIN,
104  translation_key="unloaded_config_entry",
105  translation_placeholders={
106  "config_entry": entry.title,
107  },
108  )
109 
110  coordinator: EnergyZeroDataUpdateCoordinator = hass.data[DOMAIN][entry_id]
111  return coordinator
112 
113 
114 async def __get_prices(
115  call: ServiceCall,
116  *,
117  hass: HomeAssistant,
118  price_type: PriceType,
119 ) -> ServiceResponse:
120  coordinator = __get_coordinator(hass, call)
121 
122  start = __get_date(call.data.get(ATTR_START))
123  end = __get_date(call.data.get(ATTR_END))
124 
125  vat = VatOption.INCLUDE
126 
127  if call.data.get(ATTR_INCL_VAT) is False:
128  vat = VatOption.EXCLUDE
129 
130  data: Electricity | Gas
131 
132  if price_type == PriceType.GAS:
133  data = await coordinator.energyzero.gas_prices(
134  start_date=start,
135  end_date=end,
136  vat=vat,
137  )
138  else:
139  data = await coordinator.energyzero.energy_prices(
140  start_date=start,
141  end_date=end,
142  vat=vat,
143  )
144 
145  return __serialize_prices(data)
146 
147 
148 @callback
149 def async_setup_services(hass: HomeAssistant) -> None:
150  """Set up EnergyZero services."""
151 
152  hass.services.async_register(
153  DOMAIN,
154  GAS_SERVICE_NAME,
155  partial(__get_prices, hass=hass, price_type=PriceType.GAS),
156  schema=SERVICE_SCHEMA,
157  supports_response=SupportsResponse.ONLY,
158  )
159  hass.services.async_register(
160  DOMAIN,
161  ENERGY_SERVICE_NAME,
162  partial(__get_prices, hass=hass, price_type=PriceType.ENERGY),
163  schema=SERVICE_SCHEMA,
164  supports_response=SupportsResponse.ONLY,
165  )
None async_setup_services(HomeAssistant hass)
Definition: services.py:149
EnergyZeroDataUpdateCoordinator __get_coordinator(HomeAssistant hass, ServiceCall call)
Definition: services.py:88
ServiceResponse __get_prices(ServiceCall call, *HomeAssistant hass, PriceType price_type)
Definition: services.py:119
date|datetime __get_date(str|None date_input)
Definition: services.py:56
ServiceResponse __serialize_prices(Electricity|Gas prices)
Definition: services.py:73