From 37219e8d04485666a98c74e9a6b7efe29a612662 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 24 Nov 2021 21:10:26 +0100 Subject: [PATCH] Add button platform to Tuya (#60304) --- .coveragerc | 1 + homeassistant/components/tuya/button.py | 105 ++++++++++++++++++++++++ homeassistant/components/tuya/const.py | 8 +- 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/tuya/button.py diff --git a/.coveragerc b/.coveragerc index ab8e540636b..6dfca6f7acc 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1136,6 +1136,7 @@ omit = homeassistant/components/tuya/__init__.py homeassistant/components/tuya/base.py homeassistant/components/tuya/binary_sensor.py + homeassistant/components/tuya/button.py homeassistant/components/tuya/camera.py homeassistant/components/tuya/climate.py homeassistant/components/tuya/const.py diff --git a/homeassistant/components/tuya/button.py b/homeassistant/components/tuya/button.py new file mode 100644 index 00000000000..d07d6947272 --- /dev/null +++ b/homeassistant/components/tuya/button.py @@ -0,0 +1,105 @@ +"""Support for Tuya buttons.""" +from __future__ import annotations + +from typing import Any + +from tuya_iot import TuyaDevice, TuyaDeviceManager + +from homeassistant.components.button import ButtonEntity, ButtonEntityDescription +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import ENTITY_CATEGORY_CONFIG +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import HomeAssistantTuyaData +from .base import TuyaEntity +from .const import DOMAIN, TUYA_DISCOVERY_NEW, DPCode + +# All descriptions can be found here. +# https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq +BUTTONS: dict[str, tuple[ButtonEntityDescription, ...]] = { + # Robot Vacuum + # https://developer.tuya.com/en/docs/iot/fsd?id=K9gf487ck1tlo + "sd": ( + ButtonEntityDescription( + key=DPCode.RESET_DUSTER_CLOTH, + name="Reset Duster Cloth", + icon="mdi:restart", + entity_category=ENTITY_CATEGORY_CONFIG, + ), + ButtonEntityDescription( + key=DPCode.RESET_EDGE_BRUSH, + name="Reset Edge Brush", + icon="mdi:restart", + entity_category=ENTITY_CATEGORY_CONFIG, + ), + ButtonEntityDescription( + key=DPCode.RESET_FILTER, + name="Reset Filter", + icon="mdi:air-filter", + entity_category=ENTITY_CATEGORY_CONFIG, + ), + ButtonEntityDescription( + key=DPCode.RESET_MAP, + name="Reset Map", + icon="mdi:map-marker-remove", + entity_category=ENTITY_CATEGORY_CONFIG, + ), + ButtonEntityDescription( + key=DPCode.RESET_ROLL_BRUSH, + name="Reset Roll Brush", + icon="mdi:restart", + entity_category=ENTITY_CATEGORY_CONFIG, + ), + ), +} + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up Tuya buttons dynamically through Tuya discovery.""" + hass_data: HomeAssistantTuyaData = hass.data[DOMAIN][entry.entry_id] + + @callback + def async_discover_device(device_ids: list[str]) -> None: + """Discover and add a discovered Tuya buttons.""" + entities: list[TuyaButtonEntity] = [] + for device_id in device_ids: + device = hass_data.device_manager.device_map[device_id] + if descriptions := BUTTONS.get(device.category): + for description in descriptions: + if description.key in device.function: + entities.append( + TuyaButtonEntity( + device, hass_data.device_manager, description + ) + ) + + async_add_entities(entities) + + async_discover_device([*hass_data.device_manager.device_map]) + + entry.async_on_unload( + async_dispatcher_connect(hass, TUYA_DISCOVERY_NEW, async_discover_device) + ) + + +class TuyaButtonEntity(TuyaEntity, ButtonEntity): + """Tuya Button Device.""" + + def __init__( + self, + device: TuyaDevice, + device_manager: TuyaDeviceManager, + description: ButtonEntityDescription, + ) -> None: + """Init Tuya button.""" + super().__init__(device, device_manager) + self.entity_description = description + self._attr_unique_id = f"{super().unique_id}{description.key}" + + def press(self, **kwargs: Any) -> None: + """Press the button.""" + self._send_command([{"code": self.entity_description.key, "value": True}]) diff --git a/homeassistant/components/tuya/const.py b/homeassistant/components/tuya/const.py index 0173bde9a6b..672001dd3fa 100644 --- a/homeassistant/components/tuya/const.py +++ b/homeassistant/components/tuya/const.py @@ -100,6 +100,7 @@ SMARTLIFE_APP = "smartlife" PLATFORMS = [ "binary_sensor", + "button", "camera", "climate", "cover", @@ -173,8 +174,8 @@ class DPCode(str, Enum): CO2_STATE = "co2_state" CO2_VALUE = "co2_value" # CO2 concentration COLOR_DATA_V2 = "color_data_v2" - COLOUR_DATA_HSV = "colour_data_hsv" # Colored light mode COLOUR_DATA = "colour_data" # Colored light mode + COLOUR_DATA_HSV = "colour_data_hsv" # Colored light mode COLOUR_DATA_V2 = "colour_data_v2" # Colored light mode CONCENTRATION_SET = "concentration_set" # Concentration setting CONTROL = "control" @@ -243,6 +244,11 @@ class DPCode(str, Enum): RECORD_MODE = "record_mode" RECORD_SWITCH = "record_switch" # Recording switch RELAY_STATUS = "relay_status" + RESET_DUSTER_CLOTH = "reset_duster_cloth" + RESET_EDGE_BRUSH = "reset_edge_brush" + RESET_FILTER = "reset_filter" + RESET_MAP = "reset_map" + RESET_ROLL_BRUSH = "reset_roll_brush" SEEK = "seek" SENSITIVITY = "sensitivity" # Sensitivity SENSOR_HUMIDITY = "sensor_humidity"