1 """ISY Services and Commands."""
3 from __future__
import annotations
7 from pyisy.constants
import COMMAND_FRIENDLY_NAME
8 import voluptuous
as vol
14 CONF_UNIT_OF_MEASUREMENT,
23 from .const
import _LOGGER, DOMAIN
26 SERVICE_SEND_PROGRAM_COMMAND =
"send_program_command"
29 SERVICE_SEND_RAW_NODE_COMMAND =
"send_raw_node_command"
30 SERVICE_SEND_NODE_COMMAND =
"send_node_command"
31 SERVICE_GET_ZWAVE_PARAMETER =
"get_zwave_parameter"
32 SERVICE_SET_ZWAVE_PARAMETER =
"set_zwave_parameter"
33 SERVICE_RENAME_NODE =
"rename_node"
36 SERVICE_SET_ZWAVE_LOCK_USER_CODE =
"set_zwave_lock_user_code"
37 SERVICE_DELETE_ZWAVE_LOCK_USER_CODE =
"delete_zwave_lock_user_code"
39 CONF_PARAMETER =
"parameter"
40 CONF_PARAMETERS =
"parameters"
41 CONF_USER_NUM =
"user_num"
48 VALID_NODE_COMMANDS = [
61 VALID_PROGRAM_COMMANDS = [
68 "enable_run_at_startup",
69 "disable_run_at_startup",
71 VALID_PARAMETER_SIZES = [1, 2, 4]
75 """Validate the command is valid."""
76 value =
str(value).upper()
77 if value
in COMMAND_FRIENDLY_NAME:
78 assert isinstance(value, str)
80 raise vol.Invalid(
"Invalid ISY Command.")
83 SCHEMA_GROUP =
"name-address"
85 SERVICE_SEND_RAW_NODE_COMMAND_SCHEMA = {
86 vol.Required(CONF_COMMAND): vol.All(cv.string, valid_isy_commands),
87 vol.Optional(CONF_VALUE): vol.All(vol.Coerce(int), vol.Range(0, 255)),
88 vol.Optional(CONF_UNIT_OF_MEASUREMENT): vol.All(vol.Coerce(int), vol.Range(0, 120)),
89 vol.Optional(CONF_PARAMETERS, default={}): {cv.string: cv.string},
92 SERVICE_SEND_NODE_COMMAND_SCHEMA = {
93 vol.Required(CONF_COMMAND): vol.In(VALID_NODE_COMMANDS)
96 SERVICE_RENAME_NODE_SCHEMA = {vol.Required(CONF_NAME): cv.string}
98 SERVICE_GET_ZWAVE_PARAMETER_SCHEMA = {vol.Required(CONF_PARAMETER): vol.Coerce(int)}
100 SERVICE_SET_ZWAVE_PARAMETER_SCHEMA = {
101 vol.Required(CONF_PARAMETER): vol.Coerce(int),
102 vol.Required(CONF_VALUE): vol.Coerce(int),
103 vol.Required(CONF_SIZE): vol.All(vol.Coerce(int), vol.In(VALID_PARAMETER_SIZES)),
106 SERVICE_SET_USER_CODE_SCHEMA: VolDictType = {
107 vol.Required(CONF_USER_NUM): vol.Coerce(int),
108 vol.Required(CONF_CODE): vol.Coerce(int),
111 SERVICE_DELETE_USER_CODE_SCHEMA: VolDictType = {
112 vol.Required(CONF_USER_NUM): vol.Coerce(int)
115 SERVICE_SEND_PROGRAM_COMMAND_SCHEMA = vol.All(
116 cv.has_at_least_one_key(CONF_ADDRESS, CONF_NAME),
119 vol.Exclusive(CONF_NAME, SCHEMA_GROUP): cv.string,
120 vol.Exclusive(CONF_ADDRESS, SCHEMA_GROUP): cv.string,
121 vol.Required(CONF_COMMAND): vol.In(VALID_PROGRAM_COMMANDS),
122 vol.Optional(CONF_ISY): cv.string,
129 """Get entities for a domain."""
130 entities: dict[str, Entity] = {}
132 entities.update(platform.entities)
138 """Create and register services for the ISY integration."""
139 existing_services = hass.services.async_services_for_domain(DOMAIN)
140 if existing_services
and SERVICE_SEND_PROGRAM_COMMAND
in existing_services:
144 async
def async_send_program_command_service_handler(service: ServiceCall) ->
None:
145 """Handle a send program command service call."""
146 address = service.data.get(CONF_ADDRESS)
147 name = service.data.get(CONF_NAME)
148 command = service.data[CONF_COMMAND]
149 isy_name = service.data.get(CONF_ISY)
151 for config_entry_id
in hass.data[DOMAIN]:
152 isy_data = hass.data[DOMAIN][config_entry_id]
154 if isy_name
and isy_name != isy.conf[
"name"]:
158 program = isy.programs.get_by_id(address)
160 program = isy.programs.get_by_name(name)
161 if program
is not None:
162 await getattr(program, command)()
164 _LOGGER.error(
"Could not send program command; not found or enabled on the ISY")
166 hass.services.async_register(
168 service=SERVICE_SEND_PROGRAM_COMMAND,
169 service_func=async_send_program_command_service_handler,
170 schema=SERVICE_SEND_PROGRAM_COMMAND_SCHEMA,
173 async
def _async_send_raw_node_command(call: ServiceCall) ->
None:
178 hass.services.async_register(
180 service=SERVICE_SEND_RAW_NODE_COMMAND,
181 schema=cv.make_entity_service_schema(SERVICE_SEND_RAW_NODE_COMMAND_SCHEMA),
182 service_func=_async_send_raw_node_command,
185 async
def _async_send_node_command(call: ServiceCall) ->
None:
190 hass.services.async_register(
192 service=SERVICE_SEND_NODE_COMMAND,
193 schema=cv.make_entity_service_schema(SERVICE_SEND_NODE_COMMAND_SCHEMA),
194 service_func=_async_send_node_command,
197 async
def _async_get_zwave_parameter(call: ServiceCall) ->
None:
202 hass.services.async_register(
204 service=SERVICE_GET_ZWAVE_PARAMETER,
205 schema=cv.make_entity_service_schema(SERVICE_GET_ZWAVE_PARAMETER_SCHEMA),
206 service_func=_async_get_zwave_parameter,
209 async
def _async_set_zwave_parameter(call: ServiceCall) ->
None:
214 hass.services.async_register(
216 service=SERVICE_SET_ZWAVE_PARAMETER,
217 schema=cv.make_entity_service_schema(SERVICE_SET_ZWAVE_PARAMETER_SCHEMA),
218 service_func=_async_set_zwave_parameter,
221 async
def _async_rename_node(call: ServiceCall) ->
None:
226 hass.services.async_register(
228 service=SERVICE_RENAME_NODE,
229 schema=cv.make_entity_service_schema(SERVICE_RENAME_NODE_SCHEMA),
230 service_func=_async_rename_node,
236 """Unload services for the ISY integration."""
237 if hass.data[DOMAIN]:
241 existing_services = hass.services.async_services_for_domain(DOMAIN)
242 if not existing_services
or SERVICE_SEND_PROGRAM_COMMAND
not in existing_services:
245 _LOGGER.debug(
"Unloading ISY994 Services")
246 hass.services.async_remove(domain=DOMAIN, service=SERVICE_SEND_PROGRAM_COMMAND)
247 hass.services.async_remove(domain=DOMAIN, service=SERVICE_SEND_RAW_NODE_COMMAND)
248 hass.services.async_remove(domain=DOMAIN, service=SERVICE_SEND_NODE_COMMAND)
249 hass.services.async_remove(domain=DOMAIN, service=SERVICE_GET_ZWAVE_PARAMETER)
250 hass.services.async_remove(domain=DOMAIN, service=SERVICE_SET_ZWAVE_PARAMETER)
None async_unload_services(HomeAssistant hass)
str valid_isy_commands(Any value)
None async_setup_services(HomeAssistant hass)
dict[str, Entity] async_get_entities(HomeAssistant hass)
EntityServiceResponse|None entity_service_call(HomeAssistant hass, dict[str, Entity] registered_entities, str|HassJob func, ServiceCall call, Iterable[int]|None required_features=None)