1 """Provides device actions for ZHA devices."""
3 from __future__
import annotations
7 import voluptuous
as vol
8 from zha.exceptions
import ZHAException
9 from zha.zigbee.cluster_handlers.const
import (
10 CLUSTER_HANDLER_IAS_WD,
11 CLUSTER_HANDLER_INOVELLI,
13 from zha.zigbee.cluster_handlers.manufacturerspecific
import (
25 from .const
import DOMAIN
26 from .helpers
import async_get_zha_device_proxy
27 from .websocket_api
import SERVICE_WARNING_DEVICE_SQUAWK, SERVICE_WARNING_DEVICE_WARN
31 ACTION_SQUAWK =
"squawk"
35 CONF_ZHA_ACTION_TYPE =
"zha_action_type"
36 ZHA_ACTION_TYPE_SERVICE_CALL =
"service_call"
37 ZHA_ACTION_TYPE_CLUSTER_HANDLER_COMMAND =
"cluster_handler_command"
38 INOVELLI_ALL_LED_EFFECT =
"issue_all_led_effect"
39 INOVELLI_INDIVIDUAL_LED_EFFECT =
"issue_individual_led_effect"
41 DEFAULT_ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
43 vol.Required(CONF_DOMAIN): DOMAIN,
44 vol.Required(CONF_TYPE): vol.In({ACTION_SQUAWK, ACTION_WARN}),
48 INOVELLI_ALL_LED_EFFECT_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
50 vol.Required(CONF_TYPE): INOVELLI_ALL_LED_EFFECT,
51 vol.Required(CONF_DOMAIN): DOMAIN,
52 vol.Required(
"effect_type"): AllLEDEffectType.__getitem__,
53 vol.Required(
"color"): vol.All(vol.Coerce(int), vol.Range(0, 255)),
54 vol.Required(
"level"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
55 vol.Required(
"duration"): vol.All(vol.Coerce(int), vol.Range(1, 255)),
59 INOVELLI_INDIVIDUAL_LED_EFFECT_SCHEMA = INOVELLI_ALL_LED_EFFECT_SCHEMA.extend(
61 vol.Required(CONF_TYPE): INOVELLI_INDIVIDUAL_LED_EFFECT,
62 vol.Required(
"effect_type"): SingleLEDEffectType.__getitem__,
63 vol.Required(
"led_number"): vol.All(vol.Coerce(int), vol.Range(0, 6)),
68 INOVELLI_ALL_LED_EFFECT: INOVELLI_ALL_LED_EFFECT_SCHEMA,
69 INOVELLI_INDIVIDUAL_LED_EFFECT: INOVELLI_INDIVIDUAL_LED_EFFECT_SCHEMA,
72 ACTION_SCHEMA = vol.Any(
73 INOVELLI_ALL_LED_EFFECT_SCHEMA,
74 INOVELLI_INDIVIDUAL_LED_EFFECT_SCHEMA,
75 DEFAULT_ACTION_SCHEMA,
79 CLUSTER_HANDLER_IAS_WD: [
80 {CONF_TYPE: ACTION_SQUAWK, CONF_DOMAIN: DOMAIN},
81 {CONF_TYPE: ACTION_WARN, CONF_DOMAIN: DOMAIN},
83 CLUSTER_HANDLER_INOVELLI: [
84 {CONF_TYPE: INOVELLI_ALL_LED_EFFECT, CONF_DOMAIN: DOMAIN},
85 {CONF_TYPE: INOVELLI_INDIVIDUAL_LED_EFFECT, CONF_DOMAIN: DOMAIN},
89 DEVICE_ACTION_TYPES = {
90 ACTION_SQUAWK: ZHA_ACTION_TYPE_SERVICE_CALL,
91 ACTION_WARN: ZHA_ACTION_TYPE_SERVICE_CALL,
92 INOVELLI_ALL_LED_EFFECT: ZHA_ACTION_TYPE_CLUSTER_HANDLER_COMMAND,
93 INOVELLI_INDIVIDUAL_LED_EFFECT: ZHA_ACTION_TYPE_CLUSTER_HANDLER_COMMAND,
96 DEVICE_ACTION_SCHEMAS = {
97 INOVELLI_ALL_LED_EFFECT: vol.Schema(
99 vol.Required(
"effect_type"): vol.In(AllLEDEffectType.__members__.keys()),
100 vol.Required(
"color"): vol.All(vol.Coerce(int), vol.Range(0, 255)),
101 vol.Required(
"level"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
102 vol.Required(
"duration"): vol.All(vol.Coerce(int), vol.Range(1, 255)),
105 INOVELLI_INDIVIDUAL_LED_EFFECT: vol.Schema(
107 vol.Required(
"led_number"): vol.All(vol.Coerce(int), vol.Range(0, 6)),
108 vol.Required(
"effect_type"): vol.In(SingleLEDEffectType.__members__.keys()),
109 vol.Required(
"color"): vol.All(vol.Coerce(int), vol.Range(0, 255)),
110 vol.Required(
"level"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
111 vol.Required(
"duration"): vol.All(vol.Coerce(int), vol.Range(1, 255)),
117 ACTION_SQUAWK: SERVICE_WARNING_DEVICE_SQUAWK,
118 ACTION_WARN: SERVICE_WARNING_DEVICE_WARN,
121 CLUSTER_HANDLER_MAPPINGS = {
122 INOVELLI_ALL_LED_EFFECT: CLUSTER_HANDLER_INOVELLI,
123 INOVELLI_INDIVIDUAL_LED_EFFECT: CLUSTER_HANDLER_INOVELLI,
130 variables: TemplateVarsType,
131 context: Context |
None,
133 """Perform an action based on configuration."""
134 await ZHA_ACTION_TYPES[DEVICE_ACTION_TYPES[config[CONF_TYPE]]](
135 hass, config, variables, context
140 hass: HomeAssistant, config: ConfigType
142 """Validate config."""
143 schema = ACTION_SCHEMA_MAP.get(config[CONF_TYPE], DEFAULT_ACTION_SCHEMA)
144 return schema(config)
148 hass: HomeAssistant, device_id: str
149 ) -> list[dict[str, str]]:
150 """List device actions."""
153 except (KeyError, AttributeError):
157 for endpoint
in zha_device.endpoints.values()
158 for ch
in endpoint.claimed_cluster_handlers.values()
162 for cluster_handler, cluster_handler_actions
in DEVICE_ACTIONS.items()
163 for action
in cluster_handler_actions
164 if cluster_handler
in cluster_handlers
166 for action
in actions:
167 action[CONF_DEVICE_ID] = device_id
172 hass: HomeAssistant, config: ConfigType
173 ) -> dict[str, vol.Schema]:
174 """List action capabilities."""
175 if (fields := DEVICE_ACTION_SCHEMAS.get(config[CONF_TYPE]))
is None:
177 return {
"extra_fields": fields}
182 config: dict[str, Any],
183 variables: TemplateVarsType,
184 context: Context |
None,
186 action_type = config[CONF_TYPE]
187 service_name = SERVICE_NAMES[action_type]
190 except (KeyError, AttributeError):
193 service_data = {ATTR_IEEE:
str(zha_device.ieee)}
195 await hass.services.async_call(
196 DOMAIN, service_name, service_data, blocking=
True, context=context
202 config: dict[str, Any],
203 variables: TemplateVarsType,
204 context: Context |
None,
206 action_type = config[CONF_TYPE]
207 cluster_handler_name = CLUSTER_HANDLER_MAPPINGS[action_type]
210 except (KeyError, AttributeError):
213 action_cluster_handler =
None
214 for endpoint
in zha_device.endpoints.values():
215 for cluster_handler
in endpoint.all_cluster_handlers.values():
216 if cluster_handler.name == cluster_handler_name:
217 action_cluster_handler = cluster_handler
220 if action_cluster_handler
is None:
222 f
"Unable to execute cluster handler action - cluster handler: {cluster_handler_name} action:"
226 if not hasattr(action_cluster_handler, action_type):
228 f
"Unable to execute cluster handler - cluster handler: {cluster_handler_name} action:"
233 await getattr(action_cluster_handler, action_type)(**config)
234 except ZHAException
as err:
239 ZHA_ACTION_TYPE_SERVICE_CALL: _execute_service_based_action,
240 ZHA_ACTION_TYPE_CLUSTER_HANDLER_COMMAND: _execute_cluster_handler_command_based_action,
None async_call_action_from_config(HomeAssistant hass, ConfigType config, TemplateVarsType variables, Context|None context)
dict[str, vol.Schema] async_get_action_capabilities(HomeAssistant hass, ConfigType config)
list[dict[str, str]] async_get_actions(HomeAssistant hass, str device_id)
None _execute_service_based_action(HomeAssistant hass, dict[str, Any] config, TemplateVarsType variables, Context|None context)
ConfigType async_validate_action_config(HomeAssistant hass, ConfigType config)
None _execute_cluster_handler_command_based_action(HomeAssistant hass, dict[str, Any] config, TemplateVarsType variables, Context|None context)
ZHADeviceProxy async_get_zha_device_proxy(HomeAssistant hass, str device_id)