entity.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. """
  2. Common functionality for Tuya Local entities
  3. """
  4. import logging
  5. from homeassistant.const import (
  6. CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
  7. UnitOfArea,
  8. UnitOfTemperature,
  9. )
  10. from homeassistant.helpers.entity import EntityCategory
  11. _LOGGER = logging.getLogger(__name__)
  12. # These attributes should not be included in the extra state attributes
  13. BLACKLISTED_ATTRIBUTES = ["state", "available"]
  14. class TuyaLocalEntity:
  15. """Common functions for all entity types."""
  16. def _init_begin(self, device, config):
  17. self._device = device
  18. self._config = config
  19. self._attr_dps = []
  20. self._attr_translation_key = (
  21. config.translation_key or config.translation_only_key
  22. )
  23. self._attr_translation_placeholders = config.translation_placeholders
  24. return {c.name: c for c in config.dps()}
  25. def _init_end(self, dps):
  26. for d in dps.values():
  27. if not d.hidden and d.name not in BLACKLISTED_ATTRIBUTES:
  28. self._attr_dps.append(d)
  29. @property
  30. def should_poll(self):
  31. return False
  32. @property
  33. def available(self):
  34. return self._device.has_returned_state and self._config.available(self._device)
  35. @property
  36. def has_entity_name(self):
  37. return True
  38. @property
  39. def name(self):
  40. """Return the name for the UI."""
  41. own_name = self._config.name
  42. if not own_name and not self.use_device_name:
  43. # super has the translation logic
  44. own_name = getattr(super(), "name")
  45. return own_name
  46. @property
  47. def use_device_name(self):
  48. """Return whether to use the device name for the entity name"""
  49. own_name = (
  50. self._config.name
  51. or self._config.translation_key
  52. or (self._default_to_device_class_name() and self._config.device_class)
  53. )
  54. return not own_name
  55. @property
  56. def unique_id(self):
  57. """Return the unique id for this entity."""
  58. return self._config.unique_id(self._device.unique_id)
  59. @property
  60. def device_info(self):
  61. """Return the device's information."""
  62. return self._device.device_info
  63. @property
  64. def entity_category(self):
  65. """Return the entitiy's category."""
  66. return (
  67. None
  68. if self._config.entity_category is None
  69. else EntityCategory(self._config.entity_category)
  70. )
  71. @property
  72. def icon(self):
  73. """Return the icon to use in the frontend for this device."""
  74. icon = self._config.icon(self._device)
  75. if icon:
  76. return icon
  77. else:
  78. return super().icon
  79. @property
  80. def extra_state_attributes(self):
  81. """Get additional attributes that the platform itself does not support."""
  82. attr = {}
  83. for a in self._attr_dps:
  84. value = a.get_value(self._device)
  85. if value is not None or not a.optional:
  86. attr[a.name] = value
  87. return attr
  88. @property
  89. def entity_registry_enabled_default(self):
  90. """Disable deprecated entities on new installations"""
  91. return self._config.enabled_by_default(self._device)
  92. async def async_update(self):
  93. await self._device.async_refresh()
  94. async def async_added_to_hass(self):
  95. self._device.register_entity(self)
  96. if self._config.deprecated:
  97. _LOGGER.warning(self._config.deprecation_message)
  98. async def async_will_remove_from_hass(self):
  99. await self._device.async_unregister_entity(self)
  100. def on_receive(self, dps, full_poll):
  101. """Override to process dps directly as they are received"""
  102. pass
  103. UNIT_ASCII_MAP = {
  104. "C": UnitOfTemperature.CELSIUS.value,
  105. "F": UnitOfTemperature.FAHRENHEIT.value,
  106. "ugm3": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
  107. "m2": UnitOfArea.SQUARE_METERS,
  108. }
  109. def unit_from_ascii(unit):
  110. if unit in UNIT_ASCII_MAP:
  111. return UNIT_ASCII_MAP[unit]
  112. return unit