-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4c1147e
commit 3723241
Showing
22 changed files
with
1,346 additions
and
0 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
"""The easyEnergy integration.""" | ||
from __future__ import annotations | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import Platform | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.exceptions import ConfigEntryNotReady | ||
|
||
from .const import DOMAIN | ||
from .coordinator import EasyEnergyDataUpdateCoordinator | ||
|
||
PLATFORMS = [Platform.SENSOR] | ||
|
||
|
||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Set up easyEnergy from a config entry.""" | ||
|
||
coordinator = EasyEnergyDataUpdateCoordinator(hass) | ||
try: | ||
await coordinator.async_config_entry_first_refresh() | ||
except ConfigEntryNotReady: | ||
await coordinator.easyenergy.close() | ||
raise | ||
|
||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator | ||
|
||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) | ||
return True | ||
|
||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload easyEnergy config entry.""" | ||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): | ||
hass.data[DOMAIN].pop(entry.entry_id) | ||
return unload_ok |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
"""Config flow for easyEnergy integration.""" | ||
from __future__ import annotations | ||
|
||
from typing import Any | ||
|
||
from homeassistant.config_entries import ConfigFlow | ||
from homeassistant.data_entry_flow import FlowResult | ||
|
||
from .const import DOMAIN | ||
|
||
|
||
class EasyEnergyFlowHandler(ConfigFlow, domain=DOMAIN): | ||
"""Config flow for easyEnergy integration.""" | ||
|
||
VERSION = 1 | ||
|
||
async def async_step_user( | ||
self, user_input: dict[str, Any] | None = None | ||
) -> FlowResult: | ||
"""Handle the initial step.""" | ||
|
||
await self.async_set_unique_id(DOMAIN) | ||
self._abort_if_unique_id_configured() | ||
|
||
if user_input is None: | ||
return self.async_show_form(step_id="user") | ||
|
||
return self.async_create_entry( | ||
title="easyEnergy", | ||
data={}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
"""Constants for the easyEnergy integration.""" | ||
from __future__ import annotations | ||
|
||
from datetime import timedelta | ||
import logging | ||
from typing import Final | ||
|
||
DOMAIN: Final = "easyenergy" | ||
LOGGER = logging.getLogger(__package__) | ||
SCAN_INTERVAL = timedelta(minutes=10) | ||
THRESHOLD_HOUR: Final = 14 | ||
|
||
SERVICE_TYPE_DEVICE_NAMES = { | ||
"today_energy_usage": "Energy market price - Usage", | ||
"today_energy_return": "Energy market price - Return", | ||
"today_gas": "Gas market price", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
"""The Coordinator for easyEnergy.""" | ||
from __future__ import annotations | ||
|
||
from datetime import timedelta | ||
from typing import NamedTuple | ||
|
||
from easyenergy import ( | ||
EasyEnergy, | ||
EasyEnergyConnectionError, | ||
EasyEnergyNoDataError, | ||
Electricity, | ||
Gas, | ||
) | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.helpers.aiohttp_client import async_get_clientsession | ||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed | ||
from homeassistant.util import dt | ||
|
||
from .const import DOMAIN, LOGGER, SCAN_INTERVAL, THRESHOLD_HOUR | ||
|
||
|
||
class EasyEnergyData(NamedTuple): | ||
"""Class for defining data in dict.""" | ||
|
||
energy_today: Electricity | ||
energy_tomorrow: Electricity | None | ||
gas_today: Gas | None | ||
|
||
|
||
class EasyEnergyDataUpdateCoordinator(DataUpdateCoordinator[EasyEnergyData]): | ||
"""Class to manage fetching easyEnergy data from single endpoint.""" | ||
|
||
config_entry: ConfigEntry | ||
|
||
def __init__(self, hass) -> None: | ||
"""Initialize global easyEnergy data updater.""" | ||
super().__init__( | ||
hass, | ||
LOGGER, | ||
name=DOMAIN, | ||
update_interval=SCAN_INTERVAL, | ||
) | ||
|
||
self.easyenergy = EasyEnergy(session=async_get_clientsession(hass)) | ||
|
||
async def _async_update_data(self) -> EasyEnergyData: | ||
"""Fetch data from easyEnergy.""" | ||
today = dt.now().date() | ||
gas_today = None | ||
energy_tomorrow = None | ||
|
||
try: | ||
energy_today = await self.easyenergy.energy_prices( | ||
start_date=today, end_date=today | ||
) | ||
try: | ||
gas_today = await self.easyenergy.gas_prices( | ||
start_date=today, end_date=today | ||
) | ||
except EasyEnergyNoDataError: | ||
LOGGER.debug("No data for gas prices for easyEnergy integration") | ||
# Energy for tomorrow only after 14:00 UTC | ||
if dt.utcnow().hour >= THRESHOLD_HOUR: | ||
tomorrow = today + timedelta(days=1) | ||
try: | ||
energy_tomorrow = await self.easyenergy.energy_prices( | ||
start_date=tomorrow, end_date=tomorrow | ||
) | ||
except EasyEnergyNoDataError: | ||
LOGGER.debug( | ||
"No electricity data for tomorrow for easyEnergy integration" | ||
) | ||
|
||
except EasyEnergyConnectionError as err: | ||
raise UpdateFailed("Error communicating with easyEnergy API") from err | ||
|
||
return EasyEnergyData( | ||
energy_today=energy_today, | ||
energy_tomorrow=energy_tomorrow, | ||
gas_today=gas_today, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
"""Diagnostics support for easyEnergy.""" | ||
from __future__ import annotations | ||
|
||
from datetime import timedelta | ||
from typing import Any | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.core import HomeAssistant | ||
|
||
from . import EasyEnergyDataUpdateCoordinator | ||
from .const import DOMAIN | ||
from .coordinator import EasyEnergyData | ||
|
||
|
||
def get_gas_price(data: EasyEnergyData, hours: int) -> float | None: | ||
"""Get the gas price for a given hour. | ||
Args: | ||
data: The data object. | ||
hours: The number of hours to add to the current time. | ||
Returns: | ||
The gas market price value. | ||
""" | ||
if not data.gas_today: | ||
return None | ||
return data.gas_today.price_at_time( | ||
data.gas_today.utcnow() + timedelta(hours=hours) | ||
) | ||
|
||
|
||
async def async_get_config_entry_diagnostics( | ||
hass: HomeAssistant, entry: ConfigEntry | ||
) -> dict[str, Any]: | ||
"""Return diagnostics for a config entry.""" | ||
coordinator: EasyEnergyDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] | ||
|
||
return { | ||
"entry": { | ||
"title": entry.title, | ||
}, | ||
"energy_usage": { | ||
"current_hour_price": coordinator.data.energy_today.current_usage_price, | ||
"next_hour_price": coordinator.data.energy_today.price_at_time( | ||
coordinator.data.energy_today.utcnow() + timedelta(hours=1) | ||
), | ||
"average_price": coordinator.data.energy_today.average_usage_price, | ||
"max_price": coordinator.data.energy_today.extreme_usage_prices[1], | ||
"min_price": coordinator.data.energy_today.extreme_usage_prices[0], | ||
"highest_price_time": coordinator.data.energy_today.highest_usage_price_time, | ||
"lowest_price_time": coordinator.data.energy_today.lowest_usage_price_time, | ||
"percentage_of_max": coordinator.data.energy_today.pct_of_max_usage, | ||
}, | ||
"energy_return": { | ||
"current_hour_price": coordinator.data.energy_today.current_return_price, | ||
"next_hour_price": coordinator.data.energy_today.price_at_time( | ||
coordinator.data.energy_today.utcnow() + timedelta(hours=1), "return" | ||
), | ||
"average_price": coordinator.data.energy_today.average_return_price, | ||
"max_price": coordinator.data.energy_today.extreme_return_prices[1], | ||
"min_price": coordinator.data.energy_today.extreme_return_prices[0], | ||
"highest_price_time": coordinator.data.energy_today.highest_return_price_time, | ||
"lowest_price_time": coordinator.data.energy_today.lowest_return_price_time, | ||
"percentage_of_max": coordinator.data.energy_today.pct_of_max_return, | ||
}, | ||
"gas": { | ||
"current_hour_price": get_gas_price(coordinator.data, 0), | ||
"next_hour_price": get_gas_price(coordinator.data, 1), | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"domain": "easyenergy", | ||
"name": "easyEnergy", | ||
"config_flow": true, | ||
"documentation": "https://www.home-assistant.io/integrations/easyenergy", | ||
"requirements": ["easyenergy==0.1.2"], | ||
"codeowners": ["@klaasnicolaas"], | ||
"iot_class": "cloud_polling", | ||
"quality_scale": "platinum" | ||
} |
Oops, something went wrong.