diff --git a/custom_components/vesync/device_action.py b/custom_components/vesync/device_action.py new file mode 100644 index 0000000..b2c1c47 --- /dev/null +++ b/custom_components/vesync/device_action.py @@ -0,0 +1,100 @@ +"""Provides device actions for Humidifier.""" +from __future__ import annotations + +import logging + +import homeassistant.helpers.config_validation as cv +import voluptuous as vol +from homeassistant.components.device_automation import toggle_entity +from homeassistant.const import ( + ATTR_ENTITY_ID, + ATTR_MODE, + CONF_DEVICE_ID, + CONF_DOMAIN, + CONF_ENTITY_ID, + CONF_TYPE, +) +from homeassistant.core import Context, HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers import entity_registry +from homeassistant.helpers.entity import get_capability +from homeassistant.helpers.typing import ConfigType, TemplateVarsType + +from .const import DOMAIN + +_LOGGER = logging.getLogger(__name__) + +# mypy: disallow-any-generics + +SET_MODE_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend( + { + vol.Required(CONF_TYPE): "set_mode", + vol.Required(CONF_ENTITY_ID): cv.entity_domain("fan"), + vol.Required(ATTR_MODE): cv.string, + } +) + +ACTION_SCHEMA = vol.Any(SET_MODE_SCHEMA) + + +async def async_get_actions( + hass: HomeAssistant, device_id: str +) -> list[dict[str, str]]: + """List device actions for Humidifier devices.""" + registry = entity_registry.async_get(hass) + actions = await toggle_entity.async_get_actions(hass, device_id, DOMAIN) + + # Get all the integrations entities for this device + for entry in entity_registry.async_entries_for_device(registry, device_id): + if entry.domain != "fan": + continue + + base_action = { + CONF_DEVICE_ID: device_id, + CONF_DOMAIN: DOMAIN, + CONF_ENTITY_ID: entry.entity_id, + } + + actions.append({**base_action, CONF_TYPE: "set_mode"}) + + return actions + + +async def async_call_action_from_config( + hass: HomeAssistant, + config: ConfigType, + variables: TemplateVarsType, + context: Context | None, +) -> None: + """Execute a device action.""" + service_data = {ATTR_ENTITY_ID: config[CONF_ENTITY_ID]} + + if config[CONF_TYPE] != "set_mode": + return await toggle_entity.async_call_action_from_config( + hass, config, variables, context, DOMAIN + ) + + service = "set_preset_mode" + service_data["preset_mode"] = config[ATTR_MODE] + await hass.services.async_call( + "fan", service, service_data, blocking=True, context=context + ) + + +async def async_get_action_capabilities( + hass: HomeAssistant, config: ConfigType +) -> dict[str, vol.Schema]: + """List action capabilities.""" + action_type = config[CONF_TYPE] + + if action_type != "set_mode": + return {} + + try: + available_modes = ( + get_capability(hass, config[ATTR_ENTITY_ID], "preset_modes") or [] + ) + except HomeAssistantError: + available_modes = [] + fields = {vol.Required(ATTR_MODE): vol.In(available_modes)} + return {"extra_fields": vol.Schema(fields)} diff --git a/custom_components/vesync/strings.json b/custom_components/vesync/strings.json index 8c8ed7e..f700c0f 100644 --- a/custom_components/vesync/strings.json +++ b/custom_components/vesync/strings.json @@ -1,4 +1,10 @@ { + "title": "VeSync Integration for Home Assistant", + "device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}" + } + }, "config": { "flow_title": "Gateway: {gateway_id}", "step": { diff --git a/custom_components/vesync/translations/bg.json b/custom_components/vesync/translations/bg.json index bb496b3..57c7695 100644 --- a/custom_components/vesync/translations/bg.json +++ b/custom_components/vesync/translations/bg.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "step": { "user": { diff --git a/custom_components/vesync/translations/ca.json b/custom_components/vesync/translations/ca.json index 0768905..cde8de3 100644 --- a/custom_components/vesync/translations/ca.json +++ b/custom_components/vesync/translations/ca.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Ja configurat. Nom\u00e9s \u00e9s possible una sola configuraci\u00f3." diff --git a/custom_components/vesync/translations/cs.json b/custom_components/vesync/translations/cs.json index 6834b79..06f8c8c 100644 --- a/custom_components/vesync/translations/cs.json +++ b/custom_components/vesync/translations/cs.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Ji\u017e nastaveno. Je mo\u017en\u00e1 pouze jedin\u00e1 konfigurace." diff --git a/custom_components/vesync/translations/da.json b/custom_components/vesync/translations/da.json index 4803995..c2e7932 100644 --- a/custom_components/vesync/translations/da.json +++ b/custom_components/vesync/translations/da.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "step": { "user": { diff --git a/custom_components/vesync/translations/de.json b/custom_components/vesync/translations/de.json index bd1ba32..c2064dc 100644 --- a/custom_components/vesync/translations/de.json +++ b/custom_components/vesync/translations/de.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Bereits konfiguriert. Nur eine einzige Konfiguration m\u00f6glich." diff --git a/custom_components/vesync/translations/el.json b/custom_components/vesync/translations/el.json index 0fd6807..4d2e826 100644 --- a/custom_components/vesync/translations/el.json +++ b/custom_components/vesync/translations/el.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "\u0388\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af. \u039c\u03cc\u03bd\u03bf \u03bc\u03af\u03b1 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae." diff --git a/custom_components/vesync/translations/en.json b/custom_components/vesync/translations/en.json index 91e220e..2d9916a 100644 --- a/custom_components/vesync/translations/en.json +++ b/custom_components/vesync/translations/en.json @@ -1,4 +1,9 @@ { + "device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}" + } + }, "config": { "abort": { "single_instance_allowed": "Already configured. Only a single configuration possible." diff --git a/custom_components/vesync/translations/es-419.json b/custom_components/vesync/translations/es-419.json index ec0fcaf..907a37c 100644 --- a/custom_components/vesync/translations/es-419.json +++ b/custom_components/vesync/translations/es-419.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "step": { "user": { diff --git a/custom_components/vesync/translations/es.json b/custom_components/vesync/translations/es.json index dd5f95a..0552ccd 100644 --- a/custom_components/vesync/translations/es.json +++ b/custom_components/vesync/translations/es.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Ya est\u00e1 configurado. Solo es posible una \u00fanica configuraci\u00f3n." diff --git a/custom_components/vesync/translations/et.json b/custom_components/vesync/translations/et.json index 50cd017..c172323 100644 --- a/custom_components/vesync/translations/et.json +++ b/custom_components/vesync/translations/et.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Juba seadistatud. V\u00f5imalik on ainult \u00fcks seadistamine." diff --git a/custom_components/vesync/translations/fr.json b/custom_components/vesync/translations/fr.json index 80bb38b..8b90d36 100644 --- a/custom_components/vesync/translations/fr.json +++ b/custom_components/vesync/translations/fr.json @@ -1,4 +1,9 @@ { + "device_automation": { + "action_type": { + "set_mode": "Changer le mode sur {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible." diff --git a/custom_components/vesync/translations/he.json b/custom_components/vesync/translations/he.json index a5aa8e0..4cabea9 100644 --- a/custom_components/vesync/translations/he.json +++ b/custom_components/vesync/translations/he.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "\u05ea\u05e6\u05d5\u05e8\u05ea\u05d5 \u05db\u05d1\u05e8 \u05e0\u05e7\u05d1\u05e2\u05d4. \u05e8\u05e7 \u05ea\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d7\u05ea \u05d0\u05e4\u05e9\u05e8\u05d9\u05ea." diff --git a/custom_components/vesync/translations/hu.json b/custom_components/vesync/translations/hu.json index 91956af..a0c0f25 100644 --- a/custom_components/vesync/translations/hu.json +++ b/custom_components/vesync/translations/hu.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges." diff --git a/custom_components/vesync/translations/id.json b/custom_components/vesync/translations/id.json index 968f854..8edfdd4 100644 --- a/custom_components/vesync/translations/id.json +++ b/custom_components/vesync/translations/id.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Sudah dikonfigurasi. Hanya satu konfigurasi yang diizinkan." diff --git a/custom_components/vesync/translations/it.json b/custom_components/vesync/translations/it.json index 38f0c51..e04163c 100644 --- a/custom_components/vesync/translations/it.json +++ b/custom_components/vesync/translations/it.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Gi\u00e0 configurato. \u00c8 possibile una sola configurazione." diff --git a/custom_components/vesync/translations/ja.json b/custom_components/vesync/translations/ja.json index 66d7cf2..3d0b755 100644 --- a/custom_components/vesync/translations/ja.json +++ b/custom_components/vesync/translations/ja.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5358\u4e00\u306e\u8a2d\u5b9a\u3057\u304b\u3067\u304d\u307e\u305b\u3093\u3002" diff --git a/custom_components/vesync/translations/ko.json b/custom_components/vesync/translations/ko.json index a3f1fc1..71c6a84 100644 --- a/custom_components/vesync/translations/ko.json +++ b/custom_components/vesync/translations/ko.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "\uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud558\ub098\uc758 \uc778\uc2a4\ud134\uc2a4\ub9cc \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4." diff --git a/custom_components/vesync/translations/lb.json b/custom_components/vesync/translations/lb.json index 5aab1d7..dd3eb52 100644 --- a/custom_components/vesync/translations/lb.json +++ b/custom_components/vesync/translations/lb.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun m\u00e9iglech." diff --git a/custom_components/vesync/translations/lv.json b/custom_components/vesync/translations/lv.json index eab9821..5e0dd15 100644 --- a/custom_components/vesync/translations/lv.json +++ b/custom_components/vesync/translations/lv.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "step": { "user": { diff --git a/custom_components/vesync/translations/nl.json b/custom_components/vesync/translations/nl.json index ab33023..52ab0e7 100644 --- a/custom_components/vesync/translations/nl.json +++ b/custom_components/vesync/translations/nl.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Al geconfigureerd. Slecht \u00e9\u00e9n configuratie mogelijk." diff --git a/custom_components/vesync/translations/no.json b/custom_components/vesync/translations/no.json index 4eaa522..6f1095e 100644 --- a/custom_components/vesync/translations/no.json +++ b/custom_components/vesync/translations/no.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Allerede konfigurert. Bare \u00e9n enkelt konfigurasjon er mulig." diff --git a/custom_components/vesync/translations/pl.json b/custom_components/vesync/translations/pl.json index ebd17f6..000ed02 100644 --- a/custom_components/vesync/translations/pl.json +++ b/custom_components/vesync/translations/pl.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja." diff --git a/custom_components/vesync/translations/pt-BR.json b/custom_components/vesync/translations/pt-BR.json index c656860..9d6f8a7 100644 --- a/custom_components/vesync/translations/pt-BR.json +++ b/custom_components/vesync/translations/pt-BR.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "error": { "invalid_auth": "Autentica\u00e7\u00e3o invalida" diff --git a/custom_components/vesync/translations/pt.json b/custom_components/vesync/translations/pt.json index fb4e459..f0dc372 100644 --- a/custom_components/vesync/translations/pt.json +++ b/custom_components/vesync/translations/pt.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "J\u00e1 configurado. Apenas uma \u00fanica configura\u00e7\u00e3o \u00e9 poss\u00edvel." diff --git a/custom_components/vesync/translations/ru.json b/custom_components/vesync/translations/ru.json index b3ac096..41d7a52 100644 --- a/custom_components/vesync/translations/ru.json +++ b/custom_components/vesync/translations/ru.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e." diff --git a/custom_components/vesync/translations/sk.json b/custom_components/vesync/translations/sk.json index c043ef9..ea2694d 100644 --- a/custom_components/vesync/translations/sk.json +++ b/custom_components/vesync/translations/sk.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "error": { "invalid_auth": "Neplatn\u00e9 overenie" diff --git a/custom_components/vesync/translations/sl.json b/custom_components/vesync/translations/sl.json index c1069e0..84d7674 100644 --- a/custom_components/vesync/translations/sl.json +++ b/custom_components/vesync/translations/sl.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "step": { "user": { diff --git a/custom_components/vesync/translations/sv.json b/custom_components/vesync/translations/sv.json index b9eedc2..02e5b37 100644 --- a/custom_components/vesync/translations/sv.json +++ b/custom_components/vesync/translations/sv.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "step": { "user": { diff --git a/custom_components/vesync/translations/tr.json b/custom_components/vesync/translations/tr.json index 8b4f8b6..8aa60ea 100644 --- a/custom_components/vesync/translations/tr.json +++ b/custom_components/vesync/translations/tr.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "Zaten yap\u0131land\u0131r\u0131lm\u0131\u015f. Yaln\u0131zca tek bir konfig\u00fcrasyon m\u00fcmk\u00fcnd\u00fcr." diff --git a/custom_components/vesync/translations/uk.json b/custom_components/vesync/translations/uk.json index 7f6b3a4..c138437 100644 --- a/custom_components/vesync/translations/uk.json +++ b/custom_components/vesync/translations/uk.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0436\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e. \u041c\u043e\u0436\u043d\u0430 \u0434\u043e\u0434\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e." diff --git a/custom_components/vesync/translations/zh-Hans.json b/custom_components/vesync/translations/zh-Hans.json index 4147846..421e0ec 100644 --- a/custom_components/vesync/translations/zh-Hans.json +++ b/custom_components/vesync/translations/zh-Hans.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "error": { "invalid_auth": "\u9a8c\u8bc1\u7801\u65e0\u6548" diff --git a/custom_components/vesync/translations/zh-Hant.json b/custom_components/vesync/translations/zh-Hant.json index 264ad23..92963fd 100644 --- a/custom_components/vesync/translations/zh-Hant.json +++ b/custom_components/vesync/translations/zh-Hant.json @@ -1,4 +1,9 @@ { +"device_automation": { + "action_type": { + "set_mode": "Change mode on {entity_name}." + } + }, "config": { "abort": { "single_instance_allowed": "\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u88dd\u7f6e\u3002"