mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-03-29 21:03:40 +00:00
feat: Add minimum period length configuration for best and peak price sensors
This commit is contained in:
parent
f4ae8422f2
commit
1ed2c08f34
8 changed files with 89 additions and 0 deletions
|
|
@ -29,14 +29,18 @@ if TYPE_CHECKING:
|
|||
from .const import (
|
||||
CONF_BEST_PRICE_FLEX,
|
||||
CONF_BEST_PRICE_MIN_DISTANCE_FROM_AVG,
|
||||
CONF_BEST_PRICE_MIN_PERIOD_LENGTH,
|
||||
CONF_EXTENDED_DESCRIPTIONS,
|
||||
CONF_PEAK_PRICE_FLEX,
|
||||
CONF_PEAK_PRICE_MIN_DISTANCE_FROM_AVG,
|
||||
CONF_PEAK_PRICE_MIN_PERIOD_LENGTH,
|
||||
DEFAULT_BEST_PRICE_FLEX,
|
||||
DEFAULT_BEST_PRICE_MIN_DISTANCE_FROM_AVG,
|
||||
DEFAULT_BEST_PRICE_MIN_PERIOD_LENGTH,
|
||||
DEFAULT_EXTENDED_DESCRIPTIONS,
|
||||
DEFAULT_PEAK_PRICE_FLEX,
|
||||
DEFAULT_PEAK_PRICE_MIN_DISTANCE_FROM_AVG,
|
||||
DEFAULT_PEAK_PRICE_MIN_PERIOD_LENGTH,
|
||||
async_get_entity_description,
|
||||
get_entity_description,
|
||||
)
|
||||
|
|
@ -501,6 +505,37 @@ class TibberPricesBinarySensor(TibberPricesEntity, BinarySensorEntity):
|
|||
periods.append(current_period)
|
||||
return periods
|
||||
|
||||
def _filter_periods_by_min_length(self, periods: list[list[dict]], *, reverse_sort: bool) -> list[list[dict]]:
|
||||
"""
|
||||
Filter periods to only include those meeting the minimum length requirement.
|
||||
|
||||
Args:
|
||||
periods: List of periods (each period is a list of interval dicts)
|
||||
reverse_sort: True for peak price, False for best price
|
||||
|
||||
Returns:
|
||||
Filtered list of periods that meet minimum length requirement
|
||||
|
||||
"""
|
||||
options = self.coordinator.config_entry.options
|
||||
data = self.coordinator.config_entry.data
|
||||
|
||||
# Use appropriate config based on sensor type
|
||||
if reverse_sort: # Peak price
|
||||
conf_key = CONF_PEAK_PRICE_MIN_PERIOD_LENGTH
|
||||
default = DEFAULT_PEAK_PRICE_MIN_PERIOD_LENGTH
|
||||
else: # Best price
|
||||
conf_key = CONF_BEST_PRICE_MIN_PERIOD_LENGTH
|
||||
default = DEFAULT_BEST_PRICE_MIN_PERIOD_LENGTH
|
||||
|
||||
min_period_length = options.get(conf_key, data.get(conf_key, default))
|
||||
|
||||
# Convert minutes to number of 15-minute intervals
|
||||
min_intervals = min_period_length // MINUTES_PER_INTERVAL
|
||||
|
||||
# Filter out periods that are too short
|
||||
return [period for period in periods if len(period) >= min_intervals]
|
||||
|
||||
def _add_interval_ends(self, periods: list[list[dict]]) -> None:
|
||||
"""Add interval_end to each interval using per-interval interval_length."""
|
||||
for period in periods:
|
||||
|
|
@ -580,6 +615,8 @@ class TibberPricesBinarySensor(TibberPricesEntity, BinarySensorEntity):
|
|||
price_context,
|
||||
reverse_sort=reverse_sort,
|
||||
)
|
||||
# Filter periods by minimum length requirement
|
||||
periods = self._filter_periods_by_min_length(periods, reverse_sort=reverse_sort)
|
||||
self._add_interval_ends(periods)
|
||||
# Only use periods relevant for today/tomorrow for annotation and attribute calculation
|
||||
filtered_periods = self._filter_periods_today_tomorrow(periods)
|
||||
|
|
|
|||
|
|
@ -40,16 +40,20 @@ from .api import (
|
|||
from .const import (
|
||||
CONF_BEST_PRICE_FLEX,
|
||||
CONF_BEST_PRICE_MIN_DISTANCE_FROM_AVG,
|
||||
CONF_BEST_PRICE_MIN_PERIOD_LENGTH,
|
||||
CONF_EXTENDED_DESCRIPTIONS,
|
||||
CONF_PEAK_PRICE_FLEX,
|
||||
CONF_PEAK_PRICE_MIN_DISTANCE_FROM_AVG,
|
||||
CONF_PEAK_PRICE_MIN_PERIOD_LENGTH,
|
||||
CONF_PRICE_RATING_THRESHOLD_HIGH,
|
||||
CONF_PRICE_RATING_THRESHOLD_LOW,
|
||||
DEFAULT_BEST_PRICE_FLEX,
|
||||
DEFAULT_BEST_PRICE_MIN_DISTANCE_FROM_AVG,
|
||||
DEFAULT_BEST_PRICE_MIN_PERIOD_LENGTH,
|
||||
DEFAULT_EXTENDED_DESCRIPTIONS,
|
||||
DEFAULT_PEAK_PRICE_FLEX,
|
||||
DEFAULT_PEAK_PRICE_MIN_DISTANCE_FROM_AVG,
|
||||
DEFAULT_PEAK_PRICE_MIN_PERIOD_LENGTH,
|
||||
DEFAULT_PRICE_RATING_THRESHOLD_HIGH,
|
||||
DEFAULT_PRICE_RATING_THRESHOLD_LOW,
|
||||
DOMAIN,
|
||||
|
|
@ -526,6 +530,23 @@ class TibberPricesOptionsFlowHandler(OptionsFlow):
|
|||
step_id="best_price",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Optional(
|
||||
CONF_BEST_PRICE_MIN_PERIOD_LENGTH,
|
||||
default=int(
|
||||
self.config_entry.options.get(
|
||||
CONF_BEST_PRICE_MIN_PERIOD_LENGTH,
|
||||
DEFAULT_BEST_PRICE_MIN_PERIOD_LENGTH,
|
||||
)
|
||||
),
|
||||
): NumberSelector(
|
||||
NumberSelectorConfig(
|
||||
min=15,
|
||||
max=240,
|
||||
step=15,
|
||||
unit_of_measurement="min",
|
||||
mode=NumberSelectorMode.SLIDER,
|
||||
),
|
||||
),
|
||||
vol.Optional(
|
||||
CONF_BEST_PRICE_FLEX,
|
||||
default=int(
|
||||
|
|
@ -572,6 +593,23 @@ class TibberPricesOptionsFlowHandler(OptionsFlow):
|
|||
step_id="peak_price",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Optional(
|
||||
CONF_PEAK_PRICE_MIN_PERIOD_LENGTH,
|
||||
default=int(
|
||||
self.config_entry.options.get(
|
||||
CONF_PEAK_PRICE_MIN_PERIOD_LENGTH,
|
||||
DEFAULT_PEAK_PRICE_MIN_PERIOD_LENGTH,
|
||||
)
|
||||
),
|
||||
): NumberSelector(
|
||||
NumberSelectorConfig(
|
||||
min=15,
|
||||
max=240,
|
||||
step=15,
|
||||
unit_of_measurement="min",
|
||||
mode=NumberSelectorMode.SLIDER,
|
||||
),
|
||||
),
|
||||
vol.Optional(
|
||||
CONF_PEAK_PRICE_FLEX,
|
||||
default=int(
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ CONF_BEST_PRICE_FLEX = "best_price_flex"
|
|||
CONF_PEAK_PRICE_FLEX = "peak_price_flex"
|
||||
CONF_BEST_PRICE_MIN_DISTANCE_FROM_AVG = "best_price_min_distance_from_avg"
|
||||
CONF_PEAK_PRICE_MIN_DISTANCE_FROM_AVG = "peak_price_min_distance_from_avg"
|
||||
CONF_BEST_PRICE_MIN_PERIOD_LENGTH = "best_price_min_period_length"
|
||||
CONF_PEAK_PRICE_MIN_PERIOD_LENGTH = "peak_price_min_period_length"
|
||||
CONF_PRICE_RATING_THRESHOLD_LOW = "price_rating_threshold_low"
|
||||
CONF_PRICE_RATING_THRESHOLD_HIGH = "price_rating_threshold_high"
|
||||
|
||||
|
|
@ -37,6 +39,8 @@ DEFAULT_BEST_PRICE_FLEX = 15 # 15% flexibility for best price (user-facing, per
|
|||
DEFAULT_PEAK_PRICE_FLEX = -15 # 15% flexibility for peak price (user-facing, percent)
|
||||
DEFAULT_BEST_PRICE_MIN_DISTANCE_FROM_AVG = 2 # 2% minimum distance from daily average for best price
|
||||
DEFAULT_PEAK_PRICE_MIN_DISTANCE_FROM_AVG = 2 # 2% minimum distance from daily average for peak price
|
||||
DEFAULT_BEST_PRICE_MIN_PERIOD_LENGTH = 60 # 60 minutes minimum period length for best price (user-facing, minutes)
|
||||
DEFAULT_PEAK_PRICE_MIN_PERIOD_LENGTH = 60 # 60 minutes minimum period length for peak price (user-facing, minutes)
|
||||
DEFAULT_PRICE_RATING_THRESHOLD_LOW = -10 # Default rating threshold low percentage
|
||||
DEFAULT_PRICE_RATING_THRESHOLD_HIGH = 10 # Default rating threshold high percentage
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
"title": "Bestpreis-Periode Einstellungen",
|
||||
"description": "Konfiguration für den Bestpreis-Periode Binärsensor. Dieser Sensor ist während der Zeiträume mit den niedrigsten Strompreisen aktiv.",
|
||||
"data": {
|
||||
"best_price_min_period_length": "Minimale Periodenlänge",
|
||||
"best_price_flex": "Flexibilität: Maximale % über dem Mindestpreis",
|
||||
"best_price_min_distance_from_avg": "Mindestabstand: Erforderliche % unter dem Tagesdurchschnitt"
|
||||
}
|
||||
|
|
@ -104,6 +105,7 @@
|
|||
"title": "Spitzenpreis-Periode Einstellungen",
|
||||
"description": "Konfiguration für den Spitzenpreis-Periode Binärsensor. Dieser Sensor ist während der Zeiträume mit den höchsten Strompreisen aktiv.",
|
||||
"data": {
|
||||
"peak_price_min_period_length": "Minimale Periodenlänge",
|
||||
"peak_price_flex": "Flexibilität: Maximale % unter dem Höchstpreis (negativer Wert)",
|
||||
"peak_price_min_distance_from_avg": "Mindestabstand: Erforderliche % über dem Tagesdurchschnitt"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
"title": "Best Price Period Settings",
|
||||
"description": "Configure settings for the Best Price Period binary sensor. This sensor is active during periods with the lowest electricity prices.",
|
||||
"data": {
|
||||
"best_price_min_period_length": "Minimum Period Length",
|
||||
"best_price_flex": "Flexibility: Maximum % above minimum price",
|
||||
"best_price_min_distance_from_avg": "Minimum Distance: Required % below daily average"
|
||||
}
|
||||
|
|
@ -104,6 +105,7 @@
|
|||
"title": "Peak Price Period Settings",
|
||||
"description": "Configure settings for the Peak Price Period binary sensor. This sensor is active during periods with the highest electricity prices.",
|
||||
"data": {
|
||||
"peak_price_min_period_length": "Minimum Period Length",
|
||||
"peak_price_flex": "Flexibility: Maximum % below maximum price (negative value)",
|
||||
"peak_price_min_distance_from_avg": "Minimum Distance: Required % above daily average"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
"title": "Innstillinger for beste prisperiode",
|
||||
"description": "Konfigurer innstillinger for binærsensoren Beste prisperiode. Denne sensoren er aktiv i perioder med de laveste strømprisene.",
|
||||
"data": {
|
||||
"best_price_min_period_length": "Minimum periodelengde",
|
||||
"best_price_flex": "Fleksibilitet: Maksimum % over minimumspris",
|
||||
"best_price_min_distance_from_avg": "Minimumsavstand: Påkrevd % under daglig gjennomsnitt"
|
||||
}
|
||||
|
|
@ -104,6 +105,7 @@
|
|||
"title": "Innstillinger for topprisperiode",
|
||||
"description": "Konfigurer innstillinger for binærsensoren Topprisperiode. Denne sensoren er aktiv i perioder med de høyeste strømprisene.",
|
||||
"data": {
|
||||
"peak_price_min_period_length": "Minimum periodelengde",
|
||||
"peak_price_flex": "Fleksibilitet: Maksimum % under maksimumspris (negativ verdi)",
|
||||
"peak_price_min_distance_from_avg": "Minimumsavstand: Påkrevd % over daglig gjennomsnitt"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
"title": "Instellingen beste prijsperiode",
|
||||
"description": "Configureer instellingen voor de Beste Prijsperiode binaire sensor. Deze sensor is actief tijdens perioden met de laagste elektriciteitsprijzen.",
|
||||
"data": {
|
||||
"best_price_min_period_length": "Minimale periode lengte",
|
||||
"best_price_flex": "Flexibiliteit: Maximaal % boven minimumprijs",
|
||||
"best_price_min_distance_from_avg": "Minimale afstand: Vereist % onder dagelijks gemiddelde"
|
||||
}
|
||||
|
|
@ -104,6 +105,7 @@
|
|||
"title": "Instellingen piekprijsperiode",
|
||||
"description": "Configureer instellingen voor de Piekprijsperiode binaire sensor. Deze sensor is actief tijdens perioden met de hoogste elektriciteitsprijzen.",
|
||||
"data": {
|
||||
"peak_price_min_period_length": "Minimale periode lengte",
|
||||
"peak_price_flex": "Flexibiliteit: Maximaal % onder maximumprijs (negatieve waarde)",
|
||||
"peak_price_min_distance_from_avg": "Minimale afstand: Vereist % boven dagelijks gemiddelde"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
"title": "Inställningar för bästa prisperiod",
|
||||
"description": "Konfigurera inställningar för Bästa Prisperiod binärsensor. Denna sensor är aktiv under perioder med de lägsta elpriserna.",
|
||||
"data": {
|
||||
"best_price_min_period_length": "Minsta periodlängd",
|
||||
"best_price_flex": "Flexibilitet: Maximalt % över minimumpris",
|
||||
"best_price_min_distance_from_avg": "Minimiavstånd: Krävd % under dagligt genomsnitt"
|
||||
}
|
||||
|
|
@ -104,6 +105,7 @@
|
|||
"title": "Inställningar för topprisperiod",
|
||||
"description": "Konfigurera inställningar för Topprisperiod binärsensor. Denna sensor är aktiv under perioder med de högsta elpriserna.",
|
||||
"data": {
|
||||
"peak_price_min_period_length": "Minsta periodlängd",
|
||||
"peak_price_flex": "Flexibilitet: Maximalt % under maximumpris (negativt värde)",
|
||||
"peak_price_min_distance_from_avg": "Minimiavstånd: Krävd % över dagligt genomsnitt"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue