diagnostics.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. """Diagnostics support for tuya-local."""
  2. from __future__ import annotations
  3. from typing import Any
  4. from homeassistant.components.diagnostics import REDACTED
  5. from homeassistant.config_entries import ConfigEntry
  6. from homeassistant.core import HomeAssistant, callback
  7. from homeassistant.helpers import device_registry as dr, entity_registry as er
  8. from homeassistant.helpers.device_registry import DeviceEntry
  9. from .const import DOMAIN
  10. from .device import TuyaLocalDevice
  11. async def async_get_config_entry_diagnostics(
  12. hass: HomeAssistant, entry: ConfigEntry
  13. ) -> dict[str, Any]:
  14. """Return diagnostics for a config entry."""
  15. return _async_get_diagnostics(hass, entry)
  16. async def async_get_device_diagnostics(
  17. hass: HomeAssistant, entry: ConfigEntry, device: DeviceEntry
  18. ) -> dict[str, Any]:
  19. """Return diagnostics for a device entry."""
  20. return _async_get_diagnostics(hass, entry, device)
  21. @callback
  22. def _async_get_diagnostics(
  23. hass: HomeAssistant,
  24. entry: ConfigEntry,
  25. device: DeviceEntry | None = None,
  26. ) -> dict[str, Any]:
  27. """Return diagnostics for a tuya-local config entry."""
  28. hass_data = hass.data[DOMAIN][entry.data["device_id"]]
  29. data = {
  30. "name": entry.title,
  31. "type": entry.data["type"],
  32. "device_id": REDACTED,
  33. "local_key": REDACTED,
  34. "host": REDACTED,
  35. }
  36. if device:
  37. tuya_device_id = next(iter(device.identitifers))[1]
  38. data |= _async_device_as_dict(
  39. hass, hass_data.device_manager.device_map[tuya_device_id]
  40. )
  41. else:
  42. data.update(
  43. devices=[
  44. _async_device_as_dict(hass, device)
  45. for device in hass_data.device_manager.device_map.values()
  46. ]
  47. )
  48. return data
  49. @callback
  50. def _async_device_as_dict(
  51. hass: HomeAssistant, device: TuyaLocalDevice
  52. ) -> dict[str, Any]:
  53. """Represent a Tuya Local devcie as a dictionary."""
  54. # Base device information, without sensitive information
  55. data = {
  56. "name": device.name,
  57. "api_version": device._api.version,
  58. "status": device._api.dps_cache,
  59. "cached_state": device._cached_state,
  60. "pending_state": device._pending_updates,
  61. }
  62. device_registry = dr.async_get(hass)
  63. entity_registry = er.async_get(hass)
  64. hass_device = device_registry.async_get_device(identifiers={(DOMAIN, device.id)})
  65. if hass_device:
  66. data["home_assistant"] = {
  67. "name": hass_device.name,
  68. "name_by_user": hass_device.name_by_user,
  69. "disabled": hass_device.disabled,
  70. "disabled_by": hass_device.disabled_by,
  71. "entities": [],
  72. }
  73. hass_entities = er.async_entries_for_device(
  74. entity_registry,
  75. device_id=hass_device.id,
  76. include_disabled_entities=True,
  77. )
  78. for entity_entry in hass_entities:
  79. state = hass.states.get(entity_entry.entity_id)
  80. state_dict = None
  81. if state:
  82. state_dict = dict(state.as_dict())
  83. # Redact entity_picture in case it is sensitive
  84. if "entity_picture" in state_dict["attributes"]:
  85. state_dict["attributes"] = {
  86. **state_dict["attributes"],
  87. "entity_picture": REDACTED,
  88. }
  89. # Context is not useful information
  90. state_dict.pop("context", None)
  91. data["home_assistant"]["entities"].append(
  92. {
  93. "disabled": entity_entry.disabled,
  94. "disabled_by": entity_entry.disabled_by,
  95. "entity_category": entity_entry.entity_category,
  96. "device_class": entity_entry.device_class,
  97. "original_device_class": entity_entry.original_device_class,
  98. "icon": entity_entry.icon,
  99. "unit_of_measurement": entity_entry.unit_of_measurement,
  100. "state": state_dict,
  101. }
  102. )
  103. return data