ha(H4): repair key_mismatch, диагностика для ESPHome, reconfigure, переводы
- repairs: issue key_mismatch (ERROR, fixable) при состоянии key_error, ConfirmRepairFlow, снятие issue при online/unload/remove - config flow: async_step_reconfigure (меню, prefill ручной формы, unique_id_mismatch, update_reload_and_abort) — путь «перепровижинировать» - diagnostics: config/esp_home (dsn/lanip_key/key_id/host для secrets.yaml) + esp_home_masked и redacted entry_data, runtime-снимок значений (raw/display) из кэша ядра - translations: issues.key_mismatch (title/description/fix_flow) en/ru, abort unique_id_mismatch/reconfigure_successful; тест согласованности strings↔en↔ru - FglairClient.events_dropped; mock_ac: параметр key_id в фикстуре - тесты: diagnostics, repairs issue+fix-flow, reconfigure (успех/чужое устройство), translations (45 components)
This commit is contained in:
@@ -8,12 +8,19 @@ from typing import Optional
|
||||
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from pyfglair import Error, Prop, PropertyEvent, State, Template, Value, ValueKind
|
||||
from pyfglair.templates import template_info
|
||||
|
||||
from .const import AVAILABLE_STATES, CONF_DSN, DOMAIN
|
||||
from .const import (
|
||||
AVAILABLE_STATES,
|
||||
CONF_DSN,
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
DOMAIN,
|
||||
)
|
||||
from .fglair_client import FglairClient
|
||||
from .overrides import ConversionSet
|
||||
|
||||
@@ -58,6 +65,7 @@ class FglairCoordinator(DataUpdateCoordinator[FglairData]):
|
||||
)
|
||||
self.client = client
|
||||
self.conversions = conversions
|
||||
self.key_issue_id = f"key_mismatch_{client.data[CONF_DSN]}"
|
||||
self._synced = False
|
||||
self._sync_task: Optional[asyncio.Task] = None
|
||||
self._unsubs = [
|
||||
@@ -94,6 +102,7 @@ class FglairCoordinator(DataUpdateCoordinator[FglairData]):
|
||||
available=state in AVAILABLE_STATES,
|
||||
)
|
||||
self.async_set_updated_data(self.data)
|
||||
self.sync_issue(state)
|
||||
if state == State.ONLINE:
|
||||
if not self._synced and self._sync_task is None:
|
||||
self._sync_task = self.hass.async_create_task(
|
||||
@@ -116,6 +125,32 @@ class FglairCoordinator(DataUpdateCoordinator[FglairData]):
|
||||
# не могут вклиниться между чтением и присваиванием).
|
||||
self.data = self._snapshot()
|
||||
self.async_set_updated_data(self.data)
|
||||
self.sync_issue()
|
||||
|
||||
@callback
|
||||
def sync_issue(self, state: Optional[State] = None) -> None:
|
||||
"""Repair-issue key_error: создать/снять по состоянию сессии."""
|
||||
current = state if state is not None else self.data.state
|
||||
if current == State.KEY_ERROR:
|
||||
ir.async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
self.key_issue_id,
|
||||
is_fixable=True,
|
||||
severity=ir.IssueSeverity.ERROR,
|
||||
translation_key="key_mismatch",
|
||||
translation_placeholders={
|
||||
"device": self.client.data.get(CONF_NAME)
|
||||
or self.client.data[CONF_DSN],
|
||||
"host": str(self.client.data.get(CONF_HOST, "?")),
|
||||
},
|
||||
)
|
||||
else:
|
||||
ir.async_delete_issue(self.hass, DOMAIN, self.key_issue_id)
|
||||
|
||||
@callback
|
||||
def async_remove_issue(self) -> None:
|
||||
ir.async_delete_issue(self.hass, DOMAIN, self.key_issue_id)
|
||||
|
||||
@callback
|
||||
def _on_property(self, event: PropertyEvent) -> None:
|
||||
|
||||
Reference in New Issue
Block a user