vacuum.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. """
  2. Setup for different kinds of Tuya vacuum cleaners
  3. """
  4. from homeassistant.components.vacuum import (
  5. SERVICE_CLEAN_SPOT,
  6. SERVICE_RETURN_TO_BASE,
  7. SERVICE_STOP,
  8. StateVacuumEntity,
  9. VacuumActivity,
  10. VacuumEntityFeature,
  11. )
  12. from .device import TuyaLocalDevice
  13. from .entity import TuyaLocalEntity
  14. from .helpers.config import async_tuya_setup_platform
  15. from .helpers.device_config import TuyaEntityConfig
  16. async def async_setup_entry(hass, config_entry, async_add_entities):
  17. config = {**config_entry.data, **config_entry.options}
  18. await async_tuya_setup_platform(
  19. hass,
  20. async_add_entities,
  21. config,
  22. "vacuum",
  23. TuyaLocalVacuum,
  24. )
  25. class TuyaLocalVacuum(TuyaLocalEntity, StateVacuumEntity):
  26. """Representation of a Tuya Vacuum Cleaner"""
  27. def __init__(self, device: TuyaLocalDevice, config: TuyaEntityConfig):
  28. """
  29. Initialise the sensor.
  30. Args:
  31. device (TuyaLocalDevice): the device API instance.
  32. config (TuyaEntityConfig): the configuration for this entity
  33. """
  34. super().__init__()
  35. dps_map = self._init_begin(device, config)
  36. self._status_dps = dps_map.get("status")
  37. self._command_dps = dps_map.get("command")
  38. self._locate_dps = dps_map.get("locate")
  39. self._power_dps = dps_map.get("power")
  40. self._activate_dps = dps_map.get("activate")
  41. self._direction_dps = dps_map.get("direction_control")
  42. self._error_dps = dps_map.get("error")
  43. self._fan_dps = dps_map.pop("fan_speed", None)
  44. if self._status_dps is None:
  45. raise AttributeError(f"{config.config_id} is missing a status dps")
  46. self._init_end(dps_map)
  47. @property
  48. def supported_features(self):
  49. """Return the features supported by this vacuum cleaner."""
  50. support = (
  51. VacuumEntityFeature.STATE
  52. | VacuumEntityFeature.STATUS
  53. | VacuumEntityFeature.SEND_COMMAND
  54. )
  55. if self._fan_dps:
  56. support |= VacuumEntityFeature.FAN_SPEED
  57. if self._power_dps:
  58. support |= VacuumEntityFeature.TURN_ON | VacuumEntityFeature.TURN_OFF
  59. if self._locate_dps:
  60. support |= VacuumEntityFeature.LOCATE
  61. cmd_dps = self._command_dps or self._status_dps
  62. cmd_support = cmd_dps.values(self._device)
  63. if SERVICE_RETURN_TO_BASE in cmd_support:
  64. support |= VacuumEntityFeature.RETURN_HOME
  65. if SERVICE_CLEAN_SPOT in cmd_support:
  66. support |= VacuumEntityFeature.CLEAN_SPOT
  67. if SERVICE_STOP in cmd_support:
  68. support |= VacuumEntityFeature.STOP
  69. if self._activate_dps:
  70. support |= VacuumEntityFeature.START | VacuumEntityFeature.PAUSE
  71. else:
  72. if "start" in cmd_support:
  73. support |= VacuumEntityFeature.START
  74. if "pause" in cmd_support:
  75. support |= VacuumEntityFeature.PAUSE
  76. return support
  77. @property
  78. def status(self):
  79. """Return the status of the vacuum cleaner."""
  80. return self._status_dps.get_value(self._device)
  81. @property
  82. def activity(self):
  83. """Return the state of the vacuum cleaner."""
  84. status = self.status
  85. if self._error_dps and self._error_dps.get_value(self._device):
  86. return VacuumActivity.ERROR
  87. elif status in [SERVICE_RETURN_TO_BASE, "returning"]:
  88. return VacuumActivity.RETURNING
  89. elif status in ["standby", "sleep"]:
  90. return VacuumActivity.IDLE
  91. elif status == "paused":
  92. return VacuumActivity.PAUSED
  93. elif status in ["charging", "charged", "docked"]:
  94. return VacuumActivity.DOCKED
  95. elif self._power_dps and self._power_dps.get_value(self._device) is False:
  96. return VacuumActivity.IDLE
  97. elif self._activate_dps and self._activate_dps.get_value(self._device) is False:
  98. return VacuumActivity.PAUSED
  99. else:
  100. return VacuumActivity.CLEANING
  101. async def async_turn_on(self, **kwargs):
  102. """Turn on the vacuum cleaner."""
  103. if self._power_dps:
  104. await self._power_dps.async_set_value(self._device, True)
  105. async def async_turn_off(self, **kwargs):
  106. """Turn off the vacuum cleaner."""
  107. if self._power_dps:
  108. await self._power_dps.async_set_value(self._device, False)
  109. async def async_toggle(self, **kwargs):
  110. """Toggle the vacuum cleaner."""
  111. dps = self._power_dps or self._activate_dps
  112. if dps:
  113. switch_to = not dps.get_value(self._device)
  114. await dps.async_set_value(self._device, switch_to)
  115. async def async_start(self):
  116. dps = self._command_dps or self._status_dps
  117. if dps and "start" in dps.values(self._device):
  118. await dps.async_set_value(self._device, "start")
  119. elif self._activate_dps:
  120. await self._activate_dps.async_set_value(self._device, True)
  121. async def async_pause(self):
  122. """Pause the vacuum cleaner."""
  123. dps = self._command_dps or self._status_dps
  124. if dps and "pause" in dps.values(self._device):
  125. await dps.async_set_value(self._device, "pause")
  126. elif self._activate_dps:
  127. await self._activate_dps.async_set_value(self._device, False)
  128. async def async_return_to_base(self, **kwargs):
  129. """Tell the vacuum cleaner to return to its base."""
  130. dps = self._command_dps or self._status_dps
  131. if dps and SERVICE_RETURN_TO_BASE in dps.values(self._device):
  132. await dps.async_set_value(self._device, SERVICE_RETURN_TO_BASE)
  133. async def async_clean_spot(self, **kwargs):
  134. """Tell the vacuum cleaner do a spot clean."""
  135. dps = self._command_dps or self._status_dps
  136. if dps and SERVICE_CLEAN_SPOT in dps.values(self._device):
  137. await dps.async_set_value(self._device, SERVICE_CLEAN_SPOT)
  138. async def async_stop(self, **kwargs):
  139. """Tell the vacuum cleaner to stop."""
  140. dps = self._command_dps or self._status_dps
  141. if dps and SERVICE_STOP in dps.values(self._device):
  142. await dps.async_set_value(self._device, SERVICE_STOP)
  143. async def async_locate(self, **kwargs):
  144. """Locate the vacuum cleaner."""
  145. if self._locate_dps:
  146. await self._locate_dps.async_set_value(self._device, True)
  147. async def async_send_command(self, command, params=None, **kwargs):
  148. """Send a command to the vacuum cleaner."""
  149. dps = self._command_dps or self._status_dps
  150. # stop command is often present in both command and direction dps
  151. # in that case, prefer the direction dp as async_stop will cover
  152. # the commad dp seperately.
  153. if (
  154. command == SERVICE_STOP
  155. and self._direction_dps
  156. and SERVICE_STOP in self._direction_dps.values(self._device)
  157. ):
  158. dps = self._direction_dps
  159. if command in dps.values(self._device):
  160. await dps.async_set_value(self._device, command)
  161. elif self._direction_dps and command in self._direction_dps.values(
  162. self._device
  163. ):
  164. await self._direction_dps.async_set_value(self._device, command)
  165. @property
  166. def fan_speed_list(self):
  167. """Return the list of fan speeds supported"""
  168. if self._fan_dps:
  169. return self._fan_dps.values(self._device)
  170. @property
  171. def fan_speed(self):
  172. """Return the current fan speed"""
  173. if self._fan_dps:
  174. return self._fan_dps.get_value(self._device)
  175. async def async_set_fan_speed(self, fan_speed, **kwargs):
  176. """Set the fan speed of the vacuum."""
  177. if self._fan_dps:
  178. await self._fan_dps.async_set_value(self._device, fan_speed)