"""Диагностика fglair: параметры устройства для копирования в ESPHome. План §3: на странице устройства видны dsn/lanip_key/lanip_key_id/host — источник для secrets.yaml ESPHome; рядом маскированная копия ключа для пересылки дампов. Дамп доступен только администратору HA; полный ключ включён намеренно (это статический ключ модуля, не пароль облака). """ from __future__ import annotations from typing import Any from homeassistant.components.diagnostics import async_redact_data from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from pyfglair.templates import template_info from .const import ( CONF_DEVICE_PORT, CONF_DSN, CONF_HOST, CONF_LANIP_KEY, CONF_LANIP_KEY_ID, CONF_LISTEN_PORT, CONF_MODEL, CONF_NAME, CONF_TEMP_STEP, CONF_TEMPLATE, ) from .coordinator import FglairRuntime TO_REDACT = {CONF_LANIP_KEY, "password", "email"} REDACTED = "**REDACTED**" def _masked(value: Any) -> Any: if not isinstance(value, str) or not value: return REDACTED if len(value) <= 4: return REDACTED return f"{value[:4]}…{REDACTED}" async def async_get_config_entry_diagnostics( hass: HomeAssistant, entry: ConfigEntry ) -> dict[str, Any]: runtime: FglairRuntime = entry.runtime_data client = runtime.client data = client.data key = entry.data.get(CONF_LANIP_KEY) values: dict[str, Any] = {} for info in template_info(client.template): value = client.cached(info.prop) if value is None: continue values[info.name] = { "raw": value.int_value, "display": runtime.conversions.to_display( info.prop, value.int_value ), } return { "config": { CONF_HOST: data.get(CONF_HOST), CONF_DEVICE_PORT: data.get(CONF_DEVICE_PORT), CONF_DSN: data.get(CONF_DSN), CONF_NAME: data.get(CONF_NAME), CONF_MODEL: data.get(CONF_MODEL), CONF_TEMPLATE: data.get(CONF_TEMPLATE), CONF_TEMP_STEP: data.get(CONF_TEMP_STEP), CONF_LISTEN_PORT: data.get(CONF_LISTEN_PORT), }, "esp_home": { CONF_DSN: data.get(CONF_DSN), CONF_LANIP_KEY: key, CONF_LANIP_KEY_ID: data.get(CONF_LANIP_KEY_ID), CONF_HOST: data.get(CONF_HOST), }, "esp_home_masked": { CONF_DSN: data.get(CONF_DSN), CONF_LANIP_KEY: _masked(key), CONF_LANIP_KEY_ID: data.get(CONF_LANIP_KEY_ID), CONF_HOST: data.get(CONF_HOST), }, "entry_data": async_redact_data(dict(entry.data), TO_REDACT), "overrides": entry.data.get("overrides", {}), "runtime": { "state": client.state.name.lower(), "last_error": client.last_error.name.lower(), "events_dropped": client.events_dropped, "values": values, }, }