Skip to content
Merged
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
10 changes: 1 addition & 9 deletions homeassistant/components/easyenergy/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CURRENCY_EURO,
PERCENTAGE,
UnitOfEnergy,
UnitOfTime,
UnitOfVolume,
)
from homeassistant.const import CURRENCY_EURO, PERCENTAGE, UnitOfEnergy, UnitOfVolume
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
Expand Down Expand Up @@ -182,14 +176,12 @@ class EasyEnergySensorEntityDescription(SensorEntityDescription):
key="hours_priced_equal_or_lower",
translation_key="hours_priced_equal_or_lower",
service_type="today_energy_usage",
native_unit_of_measurement=UnitOfTime.HOURS,
value_fn=lambda data: data.energy_today.periods_priced_equal_or_lower,
),
EasyEnergySensorEntityDescription(
key="hours_priced_equal_or_higher",
translation_key="hours_priced_equal_or_higher",
service_type="today_energy_return",
native_unit_of_measurement=UnitOfTime.HOURS,
value_fn=lambda data: data.energy_today.return_periods_priced_equal_or_higher,
),
)
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/easyenergy/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
"name": "Time of highest price - today"
},
"hours_priced_equal_or_higher": {
"name": "Hours priced equal or higher than current - today"
"name": "Periods priced equal or higher than current - today"
},
"hours_priced_equal_or_lower": {
"name": "Hours priced equal or lower than current - today"
"name": "Periods priced equal or lower than current - today"
},
"lowest_price_time": {
"name": "Time of lowest price - today"
Expand Down
72 changes: 66 additions & 6 deletions tests/components/easyenergy/test_sensor.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Tests for the sensors provided by the easyEnergy integration."""

from datetime import timedelta
from unittest.mock import MagicMock

from easyenergy import EasyEnergyNoDataError
from easyenergy import EasyEnergyNoDataError, Electricity
import pytest

from homeassistant.components.easyenergy.const import DOMAIN
Expand All @@ -29,8 +30,9 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util

from tests.common import MockConfigEntry
from tests.common import MockConfigEntry, async_load_json_object_fixture


@pytest.mark.freeze_time("2026-04-19 13:00:00+00:00")
Expand Down Expand Up @@ -128,7 +130,7 @@ async def test_energy_usage_today(
assert not device_entry.model
assert not device_entry.sw_version

# Usage hours priced equal or lower sensor
# Usage periods priced equal or lower sensor
state = hass.states.get(
"sensor.easyenergy_today_energy_usage_hours_priced_equal_or_lower"
)
Expand All @@ -141,9 +143,10 @@ async def test_energy_usage_today(
entry.unique_id == f"{entry_id}_today_energy_usage_hours_priced_equal_or_lower"
)
assert state.state == "2"
assert ATTR_UNIT_OF_MEASUREMENT not in state.attributes
assert (
state.attributes.get(ATTR_FRIENDLY_NAME) == "Energy market price"
" - Usage Hours priced equal or lower than current - today"
" - Usage Periods priced equal or lower than current - today"
)
assert ATTR_DEVICE_CLASS not in state.attributes

Expand Down Expand Up @@ -243,7 +246,7 @@ async def test_energy_return_today(
assert not device_entry.model
assert not device_entry.sw_version

# Return hours priced equal or higher sensor
# Return periods priced equal or higher sensor
state = hass.states.get(
"sensor.easyenergy_today_energy_return_hours_priced_equal_or_higher"
)
Expand All @@ -257,9 +260,10 @@ async def test_energy_return_today(
== f"{entry_id}_today_energy_return_hours_priced_equal_or_higher"
)
assert state.state == "23"
assert ATTR_UNIT_OF_MEASUREMENT not in state.attributes
assert (
state.attributes.get(ATTR_FRIENDLY_NAME) == "Energy market price"
" - Return Hours priced equal or higher than current - today"
" - Return Periods priced equal or higher than current - today"
)
assert ATTR_DEVICE_CLASS not in state.attributes

Expand Down Expand Up @@ -321,3 +325,59 @@ async def test_no_gas_today(
state = hass.states.get("sensor.easyenergy_today_gas_current_hour_price")
assert state
assert state.state == STATE_UNKNOWN


@pytest.mark.freeze_time("2026-04-19 00:00:00+00:00")
@pytest.mark.parametrize(
("minutes", "granularity"),
[
pytest.param(60, "hour", id="hourly"),
pytest.param(15, "quarter", id="quarter-hourly"),
],
)
@pytest.mark.parametrize(
("sensor", "expected_state"),
[
pytest.param("usage_hours_priced_equal_or_lower", "3", id="usage"),
pytest.param("return_hours_priced_equal_or_higher", "2", id="return"),
],
)
async def test_price_period_counts(
hass: HomeAssistant,
mock_easyenergy: MagicMock,
mock_config_entry: MockConfigEntry,
minutes: int,
granularity: str,
sensor: str,
expected_state: str,
) -> None:
"""Test inclusive counts for distinct usage and return prices at any interval size."""
data = await async_load_json_object_fixture(hass, "today_energy.json", DOMAIN)
start = dt_util.utcnow()
interval = timedelta(minutes=minutes)
prices = [
{
**data["prices"][0],
"from": (start + index * interval).isoformat(),
"until": (start + (index + 1) * interval).isoformat(),
"granularity": granularity,
"priceIncVat": usage_price,
"invoicePrice": return_price,
}
for index, (usage_price, return_price) in enumerate(
[(0.2, 0.3), (-0.1, 0.1), (0.2, 0.3), (0.4, 0.2)]
)
]
mock_easyenergy.energy_prices.return_value = Electricity.from_dict(
prices, price_key="priceIncVat", return_price_key="invoicePrice"
)
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()

state = hass.states.get(f"sensor.easyenergy_today_energy_{sensor}")
assert state
assert state.state == expected_state
assert ATTR_UNIT_OF_MEASUREMENT not in state.attributes
assert ATTR_DEVICE_CLASS not in state.attributes
assert ATTR_STATE_CLASS not in state.attributes
Loading