fix(coordinator): preserve currency and home_id in re-transform calls

All three re-transform sites (_handle_options_update,
async_handle_config_override_update, _perform_midnight_data_rotation)
were building raw_data with only {'price_info': ...}, omitting
'currency' and 'home_id'.

data_transformation.py's transform_data() falls back to currency='EUR'
and home_id='' when those keys are missing. This caused all non-EUR
users (Norway/NOK, Sweden/SEK) to see wrong currency units in sensors
after every midnight turnover and after any options/override change,
until the next full API poll refilled coordinator.data with correct
values (up to 15 minutes of wrong units).

Fix: explicitly carry over coordinator.data's existing currency and
home_id into each raw_data dict. Also inline the redundant lambda
wrapper on calculate_periods_fn (PLW0108 ruff lint).

Impact: Norwegian and Swedish users no longer see EUR/ct units after
midnight or config changes. Sensor unit-of-measurement stays consistent
throughout the day regardless of re-transform triggers.
This commit is contained in:
Julian Pawlowski 2026-04-06 13:51:59 +00:00
parent f8fd0f4936
commit b324bf7458

View file

@ -223,9 +223,7 @@ class TibberPricesDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
self._data_transformer = TibberPricesDataTransformer( self._data_transformer = TibberPricesDataTransformer(
config_entry=config_entry, config_entry=config_entry,
log_prefix=self._log_prefix, log_prefix=self._log_prefix,
calculate_periods_fn=lambda price_info: self._period_calculator.calculate_periods_for_price_info( calculate_periods_fn=self._period_calculator.calculate_periods_for_price_info,
price_info
),
time=self.time, time=self.time,
) )
self._repair_manager = TibberPricesRepairManager( self._repair_manager = TibberPricesRepairManager(
@ -280,8 +278,14 @@ class TibberPricesDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
# This updates rating_levels, volatility, and period calculations # This updates rating_levels, volatility, and period calculations
# without needing to fetch new data from the API # without needing to fetch new data from the API
if self.data and "priceInfo" in self.data: if self.data and "priceInfo" in self.data:
# Extract raw price_info and re-transform # Extract raw price_info and re-transform.
raw_data = {"price_info": self.data["priceInfo"]} # CRITICAL: Preserve currency and home_id so non-EUR users don't see
# wrong units (e.g. EUR instead of NOK/SEK) until the next API poll.
raw_data = {
"price_info": self.data["priceInfo"],
"currency": self.data.get("currency", "EUR"),
"home_id": self._home_id,
}
self.data = self._transform_data(raw_data) self.data = self._transform_data(raw_data)
self.async_update_listeners() self.async_update_listeners()
else: else:
@ -387,9 +391,14 @@ class TibberPricesDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
self._data_transformer.invalidate_config_cache() self._data_transformer.invalidate_config_cache()
self._period_calculator.invalidate_config_cache() self._period_calculator.invalidate_config_cache()
# Re-transform existing data with new configuration # Re-transform existing data with new configuration.
# CRITICAL: Preserve currency and home_id (same fix as _handle_options_update).
if self.data and "priceInfo" in self.data: if self.data and "priceInfo" in self.data:
raw_data = {"price_info": self.data["priceInfo"]} raw_data = {
"price_info": self.data["priceInfo"],
"currency": self.data.get("currency", "EUR"),
"home_id": self._home_id,
}
self.data = self._transform_data(raw_data) self.data = self._transform_data(raw_data)
self.async_update_listeners() self.async_update_listeners()
else: else:
@ -577,8 +586,13 @@ class TibberPricesDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
# no data rotation needed! get_intervals_for_day_offsets() automatically # no data rotation needed! get_intervals_for_day_offsets() automatically
# filters by date. Just re-transform to refresh enrichment. # filters by date. Just re-transform to refresh enrichment.
if self.data and "priceInfo" in self.data: if self.data and "priceInfo" in self.data:
# Re-transform data to ensure enrichment is refreshed for new day # Re-transform data to ensure enrichment is refreshed for new day.
raw_data = {"price_info": self.data["priceInfo"]} # CRITICAL: Preserve currency and home_id (same fix as _handle_options_update).
raw_data = {
"price_info": self.data["priceInfo"],
"currency": self.data.get("currency", "EUR"),
"home_id": self._home_id,
}
self.data = self._transform_data(raw_data) self.data = self._transform_data(raw_data)
# Mark turnover as done for today (atomic update) # Mark turnover as done for today (atomic update)