Repairs System
The Tibber Prices integration includes a proactive repair notification system that alerts users to important issues requiring attention. This system leverages Home Assistant's built-in issue_registry to create user-facing notifications in the UI.
Overview​
The repairs system is implemented in coordinator/repairs.py via the TibberPricesRepairManager class, which is instantiated in the coordinator and integrated into the update cycle.
Design Principles:
- Proactive: Detect issues before they become critical
- User-friendly: Clear explanations with actionable guidance
- Auto-clearing: Repairs automatically disappear when conditions resolve
- Non-blocking: Integration continues to work even with active repairs
Implemented Repair Types​
1. Tomorrow Data Missing​
Issue ID: tomorrow_data_missing_{entry_id}
When triggered:
- Current time is after 18:00 (configurable via
TOMORROW_DATA_WARNING_HOUR) - Tomorrow's electricity price data is still not available
When cleared:
- Tomorrow's data becomes available
- Automatically checks on every successful API update
User impact: Users cannot plan ahead for tomorrow's electricity usage optimization. Automations relying on tomorrow's prices will not work.
Implementation:
# In coordinator update cycle
has_tomorrow_data = self._data_fetcher.has_tomorrow_data(result["priceInfo"])
await self._repair_manager.check_tomorrow_data_availability(
has_tomorrow_data=has_tomorrow_data,
current_time=current_time,
)
Translation placeholders:
home_name: Name of the affected homewarning_hour: Hour after which warning appears (default: 18)
2. Rate Limit Exceeded​
Issue ID: rate_limit_exceeded_{entry_id}
When triggered:
- Integration encounters 3 or more consecutive rate limit errors (HTTP 429)
- Threshold configurable via
RATE_LIMIT_WARNING_THRESHOLD
When cleared:
- Successful API call completes (no rate limit error)
- Error counter resets to 0
User impact: API requests are being throttled, causing stale data. Updates may be delayed until rate limit expires.
Implementation:
# In error handler
is_rate_limit = (
"429" in error_str
or "rate limit" in error_str
or "too many requests" in error_str
)
if is_rate_limit:
await self._repair_manager.track_rate_limit_error()
# On successful update
await self._repair_manager.clear_rate_limit_tracking()
Translation placeholders:
home_name: Name of the affected homeerror_count: Number of consecutive rate limit errors
3. Home Not Found​
Issue ID: home_not_found_{entry_id}
When triggered:
- Home configured in this integration is no longer present in Tibber account
- Detected during user data refresh (daily check)
When cleared:
- Home reappears in Tibber account (unlikely - manual cleanup expected)
- Integration entry is removed (shutdown cleanup)
User impact: Integration cannot fetch data for a non-existent home. User must remove the config entry and re-add if needed.
Implementation:
# After user data update
home_exists = self._data_fetcher._check_home_exists(home_id)
if not home_exists:
await self._repair_manager.create_home_not_found_repair()
else:
await self._repair_manager.clear_home_not_found_repair()
Translation placeholders:
home_name: Name of the missing homeentry_id: Config entry ID for reference
Configuration Constants​
Defined in coordinator/constants.py:
TOMORROW_DATA_WARNING_HOUR = 18 # Hour after which to warn about missing tomorrow data
RATE_LIMIT_WARNING_THRESHOLD = 3 # Number of consecutive errors before creating repair
Architecture​
Class Structure​
class TibberPricesRepairManager:
"""Manages repair issues for a single Tibber home."""
def __init__(
self,
hass: HomeAssistant,
entry_id: str,
home_name: str,
) -> None:
"""Initialize repair manager."""
self._hass = hass
self._entry_id = entry_id
self._home_name = home_name
# State tracking
self._tomorrow_data_repair_active = False
self._rate_limit_error_count = 0
self._rate_limit_repair_active = False
self._home_not_found_repair_active = False
State Tracking​
Each repair type maintains internal state to avoid redundant operations:
_tomorrow_data_repair_active: Boolean flag, prevents creating duplicate repairs_rate_limit_error_count: Integer counter, tracks consecutive errors_rate_limit_repair_active: Boolean flag, tracks repair status_home_not_found_repair_active: Boolean flag, one-time repair (manual cleanup)
Lifecycle Integration​
Coordinator Initialization:
self._repair_manager = TibberPricesRepairManager(
hass=hass,
entry_id=self.config_entry.entry_id,
home_name=self._home_name,
)
Update Cycle Integration:
# Success path - check conditions
if result and "priceInfo" in result:
has_tomorrow_data = self._data_fetcher.has_tomorrow_data(result["priceInfo"])
await self._repair_manager.check_tomorrow_data_availability(
has_tomorrow_data=has_tomorrow_data,
current_time=current_time,
)
await self._repair_manager.clear_rate_limit_tracking()
# Error path - track rate limits
if is_rate_limit:
await self._repair_manager.track_rate_limit_error()
Shutdown Cleanup:
async def async_shutdown(self) -> None:
"""Shut down coordinator and clean up."""
await self._repair_manager.clear_all_repairs()
# ... other cleanup ...
Translation System​
Repairs use Home Assistant's standard translation system. Translations are defined in:
/translations/en.json/translations/de.json/translations/nb.json/translations/nl.json/translations/sv.json
Structure:
{
"issues": {
"tomorrow_data_missing": {
"title": "Tomorrow's price data missing for {home_name}",
"description": "Detailed explanation with multiple paragraphs...\n\nPossible causes:\n- Cause 1\n- Cause 2"
}
}
}
Home Assistant Integration​
Repairs appear in:
- Settings → System → Repairs (main repairs panel)
- Notifications (bell icon in UI shows repair count)
Repair properties:
is_fixable=False: No automated fix available (user action required)severity=IssueSeverity.WARNING: Yellow warning level (not critical)translation_key: Referencesissues.{key}in translation files
Testing Repairs​
Tomorrow Data Missing​
- Wait until after 18:00 local time
- Ensure integration has no tomorrow price data
- Repair should appear in UI
- When tomorrow data arrives (next API fetch), repair clears
Manual trigger:
# Temporarily set warning hour to current hour for testing
TOMORROW_DATA_WARNING_HOUR = datetime.now().hour
Rate Limit Exceeded​
- Simulate 3+ consecutive rate limit errors
- Repair should appear after 3rd error
- Successful API call clears the repair
Manual test:
- Reduce API polling interval to trigger rate limiting
- Or temporarily return HTTP 429 in API client
Home Not Found​
- Remove home from Tibber account via app/web
- Wait for user data refresh (daily check)
- Repair appears indicating home is missing
- Remove integration entry to clear repair
Adding New Repair Types​
To add a new repair type:
- Add constants (if needed) in
coordinator/constants.py - Add state tracking in
TibberPricesRepairManager.__init__ - Implement check method with create/clear logic
- Add translations to all 5 language files
- Integrate into coordinator update cycle or error handlers
- Add cleanup to
clear_all_repairs()method - Document in this file
Example template:
async def check_new_condition(self, *, param: bool) -> None:
"""Check new condition and create/clear repair."""
should_warn = param # Your condition logic
if should_warn and not self._new_repair_active:
await self._create_new_repair()
elif not should_warn and self._new_repair_active:
await self._clear_new_repair()
async def _create_new_repair(self) -> None:
"""Create new repair issue."""
_LOGGER.warning("New issue detected - creating repair")
ir.async_create_issue(
self._hass,
DOMAIN,
f"new_issue_{self._entry_id}",
is_fixable=False,
severity=ir.IssueSeverity.WARNING,
translation_key="new_issue",
translation_placeholders={
"home_name": self._home_name,
},
)
self._new_repair_active = True
async def _clear_new_repair(self) -> None:
"""Clear new repair issue."""
_LOGGER.debug("New issue resolved - clearing repair")
ir.async_delete_issue(
self._hass,
DOMAIN,
f"new_issue_{self._entry_id}",
)
self._new_repair_active = False
Best Practices​
- Always use state tracking - Prevents duplicate repair creation
- Auto-clear when resolved - Improves user experience
- Clear on shutdown - Prevents orphaned repairs
- Use descriptive issue IDs - Include entry_id for multi-home setups
- Provide actionable guidance - Tell users what they can do
- Use appropriate severity - WARNING for most cases, ERROR only for critical
- Test all language translations - Ensure placeholders work correctly
- Document expected behavior - What triggers, what clears, what user should do
Future Enhancements​
Potential additions to the repairs system:
- Stale data warning: Alert when cache is >24 hours old with no API updates
- Missing permissions: Detect insufficient API token scopes
- Config migration needed: Notify users of breaking changes requiring reconfiguration
- Extreme price alert: Warn when prices exceed historical thresholds (optional, user-configurable)
References​
- Home Assistant Repairs Documentation: https://developers.home-assistant.io/docs/core/platform/repairs
- Issue Registry API:
homeassistant.helpers.issue_registry - Integration Constants:
custom_components/tibber_prices/const.py - Repair Manager Implementation:
custom_components/tibber_prices/coordinator/repairs.py