Home Assistant Unofficial Reference 2024.12.1
alarm_control_panel.py
Go to the documentation of this file.
1 """Support for Envisalink-based alarm control panels (Honeywell/DSC)."""
2 
3 from __future__ import annotations
4 
5 import logging
6 
7 import voluptuous as vol
8 
10  AlarmControlPanelEntity,
11  AlarmControlPanelEntityFeature,
12  AlarmControlPanelState,
13  CodeFormat,
14 )
15 from homeassistant.const import ATTR_ENTITY_ID, CONF_CODE
16 from homeassistant.core import HomeAssistant, ServiceCall, callback
18 from homeassistant.helpers.dispatcher import async_dispatcher_connect
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
21 
22 from . import (
23  CONF_PANIC,
24  CONF_PARTITIONNAME,
25  DATA_EVL,
26  DOMAIN,
27  PARTITION_SCHEMA,
28  SIGNAL_KEYPAD_UPDATE,
29  SIGNAL_PARTITION_UPDATE,
30 )
31 from .entity import EnvisalinkEntity
32 
33 _LOGGER = logging.getLogger(__name__)
34 
35 SERVICE_ALARM_KEYPRESS = "alarm_keypress"
36 ATTR_KEYPRESS = "keypress"
37 ALARM_KEYPRESS_SCHEMA = vol.Schema(
38  {
39  vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
40  vol.Required(ATTR_KEYPRESS): cv.string,
41  }
42 )
43 
44 
46  hass: HomeAssistant,
47  config: ConfigType,
48  async_add_entities: AddEntitiesCallback,
49  discovery_info: DiscoveryInfoType | None = None,
50 ) -> None:
51  """Perform the setup for Envisalink alarm panels."""
52  if not discovery_info:
53  return
54  configured_partitions = discovery_info["partitions"]
55  code = discovery_info[CONF_CODE]
56  panic_type = discovery_info[CONF_PANIC]
57 
58  entities = []
59  for part_num in configured_partitions:
60  entity_config_data = PARTITION_SCHEMA(configured_partitions[part_num])
61  entity = EnvisalinkAlarm(
62  hass,
63  part_num,
64  entity_config_data[CONF_PARTITIONNAME],
65  code,
66  panic_type,
67  hass.data[DATA_EVL].alarm_state["partition"][part_num],
68  hass.data[DATA_EVL],
69  )
70  entities.append(entity)
71 
72  async_add_entities(entities)
73 
74  @callback
75  def async_alarm_keypress_handler(service: ServiceCall) -> None:
76  """Map services to methods on Alarm."""
77  entity_ids = service.data[ATTR_ENTITY_ID]
78  keypress = service.data[ATTR_KEYPRESS]
79 
80  target_entities = [
81  entity for entity in entities if entity.entity_id in entity_ids
82  ]
83 
84  for entity in target_entities:
85  entity.async_alarm_keypress(keypress)
86 
87  hass.services.async_register(
88  DOMAIN,
89  SERVICE_ALARM_KEYPRESS,
90  async_alarm_keypress_handler,
91  schema=ALARM_KEYPRESS_SCHEMA,
92  )
93 
94 
96  """Representation of an Envisalink-based alarm panel."""
97 
98  _attr_supported_features = (
99  AlarmControlPanelEntityFeature.ARM_HOME
100  | AlarmControlPanelEntityFeature.ARM_AWAY
101  | AlarmControlPanelEntityFeature.ARM_NIGHT
102  | AlarmControlPanelEntityFeature.TRIGGER
103  )
104 
105  def __init__(
106  self, hass, partition_number, alarm_name, code, panic_type, info, controller
107  ):
108  """Initialize the alarm panel."""
109  self._partition_number_partition_number = partition_number
110  self._panic_type_panic_type = panic_type
112  self._attr_code_format_attr_code_format = CodeFormat.NUMBER if not code else None
113 
114  _LOGGER.debug("Setting up alarm: %s", alarm_name)
115  super().__init__(alarm_name, info, controller)
116 
117  async def async_added_to_hass(self) -> None:
118  """Register callbacks."""
119  self.async_on_removeasync_on_remove(
121  self.hasshass, SIGNAL_KEYPAD_UPDATE, self.async_update_callbackasync_update_callback
122  )
123  )
124  self.async_on_removeasync_on_remove(
126  self.hasshass, SIGNAL_PARTITION_UPDATE, self.async_update_callbackasync_update_callback
127  )
128  )
129 
130  @callback
131  def async_update_callback(self, partition):
132  """Update Home Assistant state, if needed."""
133  if partition is None or int(partition) == self._partition_number_partition_number:
134  self.async_write_ha_stateasync_write_ha_state()
135 
136  @property
137  def alarm_state(self) -> AlarmControlPanelState | None:
138  """Return the state of the device."""
139  state = None
140 
141  if self._info_info["status"]["alarm"]:
142  state = AlarmControlPanelState.TRIGGERED
143  elif self._info_info["status"]["armed_zero_entry_delay"]:
144  state = AlarmControlPanelState.ARMED_NIGHT
145  elif self._info_info["status"]["armed_away"]:
146  state = AlarmControlPanelState.ARMED_AWAY
147  elif self._info_info["status"]["armed_stay"]:
148  state = AlarmControlPanelState.ARMED_HOME
149  elif self._info_info["status"]["exit_delay"]:
150  state = AlarmControlPanelState.ARMING
151  elif self._info_info["status"]["entry_delay"]:
152  state = AlarmControlPanelState.PENDING
153  elif self._info_info["status"]["alpha"]:
154  state = AlarmControlPanelState.DISARMED
155  return state
156 
157  async def async_alarm_disarm(self, code: str | None = None) -> None:
158  """Send disarm command."""
159  self.hasshass.data[DATA_EVL].disarm_partition(code, self._partition_number_partition_number)
160 
161  async def async_alarm_arm_home(self, code: str | None = None) -> None:
162  """Send arm home command."""
163  self.hasshass.data[DATA_EVL].arm_stay_partition(code, self._partition_number_partition_number)
164 
165  async def async_alarm_arm_away(self, code: str | None = None) -> None:
166  """Send arm away command."""
167  self.hasshass.data[DATA_EVL].arm_away_partition(code, self._partition_number_partition_number)
168 
169  async def async_alarm_trigger(self, code: str | None = None) -> None:
170  """Alarm trigger command. Will be used to trigger a panic alarm."""
171  self.hasshass.data[DATA_EVL].panic_alarm(self._panic_type_panic_type)
172 
173  async def async_alarm_arm_night(self, code: str | None = None) -> None:
174  """Send arm night command."""
175  self.hasshass.data[DATA_EVL].arm_night_partition(code, self._partition_number_partition_number)
176 
177  @callback
178  def async_alarm_keypress(self, keypress=None):
179  """Send custom keypress."""
180  if keypress:
181  self.hasshass.data[DATA_EVL].keypresses_to_partition(
182  self._partition_number_partition_number, keypress
183  )
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103