From 061b42b8f34715c254a380c5c1d846c0c1b3ffd2 Mon Sep 17 00:00:00 2001 From: Julian Pawlowski Date: Tue, 14 Apr 2026 19:28:47 +0000 Subject: [PATCH] feat(options): show persistent repair issue after currency mode change Add DATA_STATISTICS_REVIEW_REQUIRED flag to config_entry.data. Set on currency mode change, cleared on same-mode save. On every async_setup_entry with flag set, delete and recreate the repair issue so it reappears after HA restart even if previously dismissed. Repair issue text explains that HA Recorder shows its own unit-change dialog (delayed) and recommends deleting old statistic data rather than re-labeling, which would leave wrong values with the new unit. Impact: Users are notified to review statistics and automations after switching between base/subunit currency mode. Notification persists across HA restarts until acknowledged by saving display settings again. --- custom_components/tibber_prices/__init__.py | 29 ++++++++++++++ .../config_flow_handlers/options_flow.py | 39 ++++++++++++++++++- .../tibber_prices/translations/de.json | 4 ++ .../tibber_prices/translations/en.json | 4 ++ .../tibber_prices/translations/nb.json | 4 ++ .../tibber_prices/translations/nl.json | 4 ++ .../tibber_prices/translations/sv.json | 4 ++ 7 files changed, 86 insertions(+), 2 deletions(-) diff --git a/custom_components/tibber_prices/__init__.py b/custom_components/tibber_prices/__init__.py index 1854399..ac131b8 100644 --- a/custom_components/tibber_prices/__init__.py +++ b/custom_components/tibber_prices/__init__.py @@ -14,6 +14,7 @@ import voluptuous as vol from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.const import CONF_ACCESS_TOKEN, Platform from homeassistant.exceptions import ConfigEntryAuthFailed +from homeassistant.helpers import issue_registry as ir from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.storage import Store from homeassistant.loader import async_get_loaded_integration @@ -25,6 +26,7 @@ from .const import ( CONF_PRICE_TREND_MIN_PRICE_CHANGE_STRONGLY, DATA_CHART_CONFIG, DATA_CHART_METADATA_CONFIG, + DATA_STATISTICS_REVIEW_REQUIRED, DISPLAY_MODE_SUBUNIT, DOMAIN, LOGGER, @@ -212,6 +214,30 @@ def _get_access_token(hass: HomeAssistant, entry: ConfigEntry) -> str: raise ConfigEntryAuthFailed(msg) +def _check_statistics_review_repair(hass: HomeAssistant, entry: TibberPricesConfigEntry) -> None: + """Re-create the statistics-review repair issue fresh on every setup when the flag is set. + + Using delete + create (instead of get_or_create) resets dismissed_version, so the issue + reappears in the Repairs panel even if the user had dismissed it before a restart. + The flag is cleared from config_entry.data only when the user acknowledges the change + by re-saving the currency display settings in the options flow. + """ + if not entry.data.get(DATA_STATISTICS_REVIEW_REQUIRED): + return + issue_id = f"currency_display_mode_changed_{entry.entry_id}" + ir.async_delete_issue(hass, DOMAIN, issue_id) + ir.async_create_issue( + hass, + DOMAIN, + issue_id, + is_fixable=False, + is_persistent=True, + severity=ir.IssueSeverity.WARNING, + translation_key="currency_display_mode_changed", + translation_placeholders={"home_name": entry.title}, + ) + + # https://developers.home-assistant.io/docs/config_entries_index/#setting-up-an-entry async def async_setup_entry( hass: HomeAssistant, @@ -226,6 +252,9 @@ async def async_setup_entry( # Check for entity migrations (renames, breaking changes) and create repairs check_entity_migrations(hass, entry) + # Re-create statistics review repair issue fresh (resets any previous dismiss) + _check_statistics_review_repair(hass, entry) + # Preload translations to populate the cache await async_load_translations(hass, "en") await async_load_standard_translations(hass, "en") diff --git a/custom_components/tibber_prices/config_flow_handlers/options_flow.py b/custom_components/tibber_prices/config_flow_handlers/options_flow.py index fe224a6..6dcc7b0 100644 --- a/custom_components/tibber_prices/config_flow_handlers/options_flow.py +++ b/custom_components/tibber_prices/config_flow_handlers/options_flow.py @@ -2,8 +2,8 @@ from __future__ import annotations -import logging from copy import deepcopy +import logging from typing import TYPE_CHECKING, Any if TYPE_CHECKING: @@ -52,6 +52,7 @@ from custom_components.tibber_prices.const import ( CONF_BEST_PRICE_MAX_LEVEL_GAP_COUNT, CONF_BEST_PRICE_MIN_DISTANCE_FROM_AVG, CONF_BEST_PRICE_MIN_PERIOD_LENGTH, + CONF_CURRENCY_DISPLAY_MODE, CONF_MIN_PERIODS_BEST, CONF_MIN_PERIODS_PEAK, CONF_PEAK_PRICE_FLEX, @@ -71,6 +72,7 @@ from custom_components.tibber_prices.const import ( CONF_VOLATILITY_THRESHOLD_HIGH, CONF_VOLATILITY_THRESHOLD_MODERATE, CONF_VOLATILITY_THRESHOLD_VERY_HIGH, + DATA_STATISTICS_REVIEW_REQUIRED, DEFAULT_VOLATILITY_THRESHOLD_HIGH, DEFAULT_VOLATILITY_THRESHOLD_MODERATE, DEFAULT_VOLATILITY_THRESHOLD_VERY_HIGH, @@ -82,7 +84,7 @@ from custom_components.tibber_prices.const import ( get_display_unit_factor, ) from homeassistant.config_entries import ConfigFlowResult, OptionsFlow -from homeassistant.helpers import entity_registry as er +from homeassistant.helpers import entity_registry as er, issue_registry as ir _LOGGER = logging.getLogger(__name__) @@ -501,10 +503,43 @@ class TibberPricesOptionsFlowHandler(OptionsFlow): currency_code = tibber_data.coordinator.data.get("currency") if user_input is not None: + # Detect currency display mode change before saving + old_mode = self.config_entry.options.get(CONF_CURRENCY_DISPLAY_MODE) + new_mode = user_input.get(CONF_CURRENCY_DISPLAY_MODE) + # Update options with new values self._options.update(user_input) # async_create_entry automatically handles change detection and listener triggering self._save_options_if_changed() + + # Handle currency display mode change repair + persistent flag + issue_id = f"currency_display_mode_changed_{self.config_entry.entry_id}" + mode_changed = old_mode is not None and new_mode is not None and old_mode != new_mode + + if mode_changed: + # Set persistent flag so repair issue reappears after dismiss + HA restart + self.hass.config_entries.async_update_entry( + self.config_entry, + data={**self.config_entry.data, DATA_STATISTICS_REVIEW_REQUIRED: True}, + ) + ir.async_create_issue( + self.hass, + DOMAIN, + issue_id, + is_fixable=False, + is_persistent=True, + severity=ir.IssueSeverity.WARNING, + translation_key="currency_display_mode_changed", + translation_placeholders={ + "home_name": self.config_entry.title, + }, + ) + elif self.config_entry.data.get(DATA_STATISTICS_REVIEW_REQUIRED): + # User re-saved display settings with same mode = acknowledgement → clear flag + new_data = {k: v for k, v in self.config_entry.data.items() if k != DATA_STATISTICS_REVIEW_REQUIRED} + self.hass.config_entries.async_update_entry(self.config_entry, data=new_data) + ir.async_delete_issue(self.hass, DOMAIN, issue_id) + # Return to menu for more changes return await self.async_step_init() diff --git a/custom_components/tibber_prices/translations/de.json b/custom_components/tibber_prices/translations/de.json index 45e4c4e..f5d3117 100644 --- a/custom_components/tibber_prices/translations/de.json +++ b/custom_components/tibber_prices/translations/de.json @@ -1153,6 +1153,10 @@ "entity_migration": { "title": "Tibber Prices: Aktion nach Update erforderlich ({home_name})", "description": "Dieses Update enthält Breaking Changes, die automatisch angewendet wurden.\n\n**Umbenannte Entitäten ({count})**\n\nDie folgenden Entity-Keys wurden umbenannt. Deine bestehenden Entity-IDs und Automationen bleiben erhalten:\n\n{entity_list}\n\n**Geänderte Dauer-Sensorwerte**\n\nAlle Dauer-Sensoren (verbleibende Zeit, startet in, Periodendauer, Trendänderungs-Countdown) geben ihren Zustandswert jetzt in **Minuten** statt Stunden an. Die Anzeigeeinheit in Dashboards bleibt standardmäßig Stunden.\n\nWenn du Automationen mit numerischen Vergleichen auf diesen Sensoren hast, aktualisiere deine Schwellwerte:\n- Alt: `state < 0.25` (15 Minuten als Stunden)\n- Neu: `state < 15` (15 Minuten)\n\nSchließe diesen Hinweis, nachdem du deine Automationen überprüft hast." + }, + "currency_display_mode_changed": { + "title": "Währungsanzeigeeinheit für {home_name} geändert", + "description": "Du hast den Währungsanzeigemodus für **{home_name}** geändert. Alle Preissensor-Werte und -Attribute verwenden jetzt die neue Einheit (z.B. 25,34 ct → 0,2534 € oder umgekehrt).\n\nDer Recorder von Home Assistant zeigt separat einen Dialog **„Die Einheit hat sich geändert“** für betroffene Sensoren — das kann einige Minuten dauern oder bis zum nächsten Statistik-Durchlauf (Warnungen im Log erscheinen früher). Wähle dann **Alle alten Statistikdaten löschen** für einen sauberen Neustart. Wähle nicht „Einheit aktualisieren ohne Konvertierung“: das benennt die alten Zahlen nur um, ohne die Werte anzupassen, und macht die historischen Daten inhaltlich falsch.\n\n**Manuell prüfen:**\n\n1. **Automationen & Templates:** Aktualisiere alle Automationen und Template-Sensoren mit numerischen Preis-Schwellwerten.\n2. **Dashboard-Karten:** Aktualisiere alle Karten mit fest codierten Schwellwerten oder Einheitenbezeichnungen.\n\nSchließe diesen Hinweis, nachdem du deine Automationen und Dashboards überprüft hast." } }, "exceptions": { diff --git a/custom_components/tibber_prices/translations/en.json b/custom_components/tibber_prices/translations/en.json index d234144..44228f6 100644 --- a/custom_components/tibber_prices/translations/en.json +++ b/custom_components/tibber_prices/translations/en.json @@ -1153,6 +1153,10 @@ "entity_migration": { "title": "Tibber Prices: Action required after update ({home_name})", "description": "This update includes breaking changes that were applied automatically.\n\n**Renamed Entities ({count})**\n\nThe following entity keys were renamed. Your existing entity IDs and automations remain intact:\n\n{entity_list}\n\n**Duration Sensor Value Change**\n\nAll duration sensors (remaining time, starts in, period duration, trend change countdown) now report their state value in **minutes** instead of hours. The display unit in dashboards remains hours by default.\n\nIf you have automations using numeric comparisons on these sensors, update your thresholds:\n- Old: `state < 0.25` (15 minutes as hours)\n- New: `state < 15` (15 minutes)\n\nDismiss this notice after reviewing your automations." + }, + "currency_display_mode_changed": { + "title": "Currency display unit changed for {home_name}", + "description": "You changed the currency display mode for **{home_name}**. All price sensor values and attributes now use the new unit (e.g. 25.34 ct → 0.2534 € or vice versa).\n\nHome Assistant’s Recorder will separately show a **“The unit has changed”** dialog for affected sensors — this may take a few minutes or until the next statistics run (log warnings appear earlier). When it appears, choose **Delete all old statistic data** to start fresh. Do not choose “Update the unit without converting”: that re-labels the old numbers without adjusting their values, making the historic data factually incorrect.\n\n**Review manually:**\n\n1. **Automations & Templates:** Update all automations and template sensors that use numeric price thresholds.\n2. **Dashboard Cards:** Update any cards with hardcoded thresholds or unit labels.\n\nDismiss this notice after reviewing your automations and dashboards." } }, "exceptions": { diff --git a/custom_components/tibber_prices/translations/nb.json b/custom_components/tibber_prices/translations/nb.json index f5ea852..68e8839 100644 --- a/custom_components/tibber_prices/translations/nb.json +++ b/custom_components/tibber_prices/translations/nb.json @@ -1153,6 +1153,10 @@ "entity_migration": { "title": "Tibber Prices: Handling kreves etter oppdatering ({home_name})", "description": "Denne oppdateringen inkluderer endringer som ble brukt automatisk.\n\n**Omdøpte entiteter ({count})**\n\nFølgende entity-nøkler ble omdøpt. Dine eksisterende entity-ID-er og automatiseringer forblir intakte:\n\n{entity_list}\n\n**Endrede varighetssensorverdier**\n\nAlle varighetssensorer (gjenværende tid, starter om, periodevarighet, trendendrings-nedtelling) rapporterer nå tilstandsverdien i **minutter** i stedet for timer. Visningsenheten i dashboards forblir timer som standard.\n\nHvis du har automatiseringer med numeriske sammenligninger på disse sensorene, oppdater tersklene:\n- Gammelt: `state < 0.25` (15 minutter som timer)\n- Nytt: `state < 15` (15 minutter)\n\nAvvis dette varselet etter å ha gjennomgått automatiseringene dine." + }, + "currency_display_mode_changed": { + "title": "Valutavisningsenhet endret for {home_name}", + "description": "Du endret valutavisningsmodusen for **{home_name}**. Alle prissensorverdier og -attributter bruker nå den nye enheten (f.eks. 25,34 øre → 0,2534 kr eller omvendt).\n\nHome Assistants Recorder viser separat en **„Enheten har endret seg“**-dialog for berørte sensorer — dette kan ta noen minutter eller til neste statistikkjøring (advarsler i loggen dukker opp tidligere). Når den vises, velg **Slett alle gamle statistikkdata** for en ren start. Ikke velg „Oppdater enheten uten konvertering“: det beholder de gamle tallene med ny enhet uten å justere verdiene, og gjør de historiske dataene faktisk feil.\n\n**Gjennomgå manuelt:**\n\n1. **Automatiseringer & maler:** Oppdater alle automatiseringer og malsensorer som bruker numeriske pristerskler.\n2. **Dashboard-kort:** Oppdater kort med hardkodede terskelverdier eller enhetsetiketter.\n\nAvvis dette varselet etter å ha gjennomgått automatiseringene og dashboardene dine." } }, "exceptions": { diff --git a/custom_components/tibber_prices/translations/nl.json b/custom_components/tibber_prices/translations/nl.json index 489bbf9..c95fe03 100644 --- a/custom_components/tibber_prices/translations/nl.json +++ b/custom_components/tibber_prices/translations/nl.json @@ -1153,6 +1153,10 @@ "entity_migration": { "title": "Tibber Prices: Actie vereist na update ({home_name})", "description": "Deze update bevat wijzigingen die automatisch zijn toegepast.\n\n**Hernoemde entiteiten ({count})**\n\nDe volgende entity-sleutels zijn hernoemd. Je bestaande entity-ID's en automatiseringen blijven intact:\n\n{entity_list}\n\n**Gewijzigde duur-sensorwaarden**\n\nAlle duur-sensoren (resterende tijd, start over, periodeduur, trendwijzigings-aftelling) rapporteren hun statuswaarde nu in **minuten** in plaats van uren. De weergave-eenheid in dashboards blijft standaard uren.\n\nAls je automatiseringen hebt met numerieke vergelijkingen op deze sensoren, werk dan je drempelwaarden bij:\n- Oud: `state < 0.25` (15 minuten als uren)\n- Nieuw: `state < 15` (15 minuten)\n\nSluit deze melding nadat je je automatiseringen hebt gecontroleerd." + }, + "currency_display_mode_changed": { + "title": "Valutaweergave-eenheid gewijzigd voor {home_name}", + "description": "Je hebt de valutaweergavemodus voor **{home_name}** gewijzigd. Alle prijssensorwaarden en -attributen gebruiken nu de nieuwe eenheid (bijv. 25,34 ct → 0,2534 € of andersom).\n\nHome Assistant’s Recorder toont afzonderlijk een **„De eenheid is gewijzigd“**-dialoogvenster voor getroffen sensoren — dit kan enkele minuten duren of tot de volgende statistiekenrun (logwaarschuwingen verschijnen eerder). Kies dan **Alle oude statistiekgegevens verwijderen** voor een schone start. Kies niet „Eenheid bijwerken zonder conversie“: dat hernoemt de oude getallen zonder de waarden aan te passen, waardoor de historische gegevens inhoudelijk onjuist worden.\n\n**Handmatig controleren:**\n\n1. **Automatiseringen & templates:** Werk alle automatiseringen en template-sensoren bij die numerieke prijsdrempels gebruiken.\n2. **Dashboard-kaarten:** Werk kaarten bij met hardgecodeerde drempelwaarden of eenheidslabels.\n\nSluit deze melding nadat je je automatiseringen en dashboards hebt gecontroleerd." } }, "exceptions": { diff --git a/custom_components/tibber_prices/translations/sv.json b/custom_components/tibber_prices/translations/sv.json index 64f864e..1a94e0d 100644 --- a/custom_components/tibber_prices/translations/sv.json +++ b/custom_components/tibber_prices/translations/sv.json @@ -1153,6 +1153,10 @@ "entity_migration": { "title": "Tibber Prices: Åtgärd krävs efter uppdatering ({home_name})", "description": "Denna uppdatering innehåller ändringar som tillämpades automatiskt.\n\n**Omdöpta entiteter ({count})**\n\nFöljande entity-nycklar döptes om automatiskt. Dina befintliga entity-ID:n och automatiseringar förblir intakta:\n\n{entity_list}\n\n**Ändrade varaktighetssensorvärden**\n\nAlla varaktighetssensorer (återstående tid, startar om, periodvaraktighet, trendändrings-nedräkning) rapporterar nu sitt tillståndsvärde i **minuter** istället för timmar. Visningsenheten i dashboards förblir timmar som standard.\n\nOm du har automatiseringar med numeriska jämförelser på dessa sensorer, uppdatera dina tröskelvärden:\n- Gammalt: `state < 0.25` (15 minuter som timmar)\n- Nytt: `state < 15` (15 minuter)\n\nStäng detta meddelande efter att du har granskat dina automatiseringar." + }, + "currency_display_mode_changed": { + "title": "Valutavisningsenhet ändrad för {home_name}", + "description": "Du ändrade valutavisningsläget för **{home_name}**. Alla prissensorvärden och -attribut använder nu den nya enheten (t.ex. 25,34 öre → 0,2534 kr eller tvärtom).\n\nHome Assistants Recorder visar separat en **„Enheten har ändrats“**-dialog för berörda sensorer — det kan ta några minuter eller till nästa statistikkörning (loggvarningar dyker upp tidigare). När den visas, välj **Ta bort alla gamla statistikdata** för en ren start. Välj inte „Uppdatera enheten utan konvertering“: det behåller de gamla talen med ny enhet utan att justera värdena, vilket gör historiska data faktiskt felaktiga.\n\n**Granska manuellt:**\n\n1. **Automatiseringar & mallar:** Uppdatera alla automatiseringar och mallsensorer som använder numeriska priströsklar.\n2. **Dashboard-kort:** Uppdatera kort med hårdkodade tröskelvärden eller enhetsetiketter.\n\nStäng detta meddelande efter att du har granskat dina automatiseringar och dashboards." } }, "exceptions": {